console: block rendering until client is done
[qemu/kevin.git] / tests / test-qga.c
blobe6a84d17f0626e0521ce5e252be0c393fb438dfb
1 #include <locale.h>
2 #include <glib.h>
3 #include <glib/gstdio.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <sys/types.h>
9 #include <sys/socket.h>
10 #include <sys/un.h>
11 #include <unistd.h>
12 #include <inttypes.h>
14 #include "libqtest.h"
15 #include "config-host.h"
16 #include "qga/guest-agent-core.h"
18 typedef struct {
19 char *test_dir;
20 GMainLoop *loop;
21 int fd;
22 GPid pid;
23 } TestFixture;
25 static int connect_qga(char *path)
27 int s, ret, len, i = 0;
28 struct sockaddr_un remote;
30 s = socket(AF_UNIX, SOCK_STREAM, 0);
31 g_assert(s != -1);
33 remote.sun_family = AF_UNIX;
34 do {
35 strcpy(remote.sun_path, path);
36 len = strlen(remote.sun_path) + sizeof(remote.sun_family);
37 ret = connect(s, (struct sockaddr *)&remote, len);
38 if (ret == -1) {
39 g_usleep(G_USEC_PER_SEC);
41 if (i++ == 10) {
42 return -1;
44 } while (ret == -1);
46 return s;
49 static void qga_watch(GPid pid, gint status, gpointer user_data)
51 TestFixture *fixture = user_data;
53 g_assert_cmpint(status, ==, 0);
54 g_main_loop_quit(fixture->loop);
57 static void
58 fixture_setup(TestFixture *fixture, gconstpointer data)
60 const gchar *extra_arg = data;
61 GError *error = NULL;
62 gchar *cwd, *path, *cmd, **argv = NULL;
64 fixture->loop = g_main_loop_new(NULL, FALSE);
66 fixture->test_dir = g_strdup("/tmp/qgatest.XXXXXX");
67 g_assert_nonnull(mkdtemp(fixture->test_dir));
69 path = g_build_filename(fixture->test_dir, "sock", NULL);
70 cwd = g_get_current_dir();
71 cmd = g_strdup_printf("%s%cqemu-ga -m unix-listen -t %s -p %s %s %s",
72 cwd, G_DIR_SEPARATOR,
73 fixture->test_dir, path,
74 getenv("QTEST_LOG") ? "-v" : "",
75 extra_arg ?: "");
76 g_shell_parse_argv(cmd, NULL, &argv, &error);
77 g_assert_no_error(error);
79 g_spawn_async(fixture->test_dir, argv, NULL,
80 G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
81 NULL, NULL, &fixture->pid, &error);
82 g_assert_no_error(error);
84 g_child_watch_add(fixture->pid, qga_watch, fixture);
86 fixture->fd = connect_qga(path);
87 g_assert_cmpint(fixture->fd, !=, -1);
89 g_strfreev(argv);
90 g_free(cmd);
91 g_free(cwd);
92 g_free(path);
95 static void
96 fixture_tear_down(TestFixture *fixture, gconstpointer data)
98 gchar *tmp;
100 kill(fixture->pid, SIGTERM);
102 g_main_loop_run(fixture->loop);
103 g_main_loop_unref(fixture->loop);
105 g_spawn_close_pid(fixture->pid);
107 tmp = g_build_filename(fixture->test_dir, "foo", NULL);
108 g_unlink(tmp);
109 g_free(tmp);
111 tmp = g_build_filename(fixture->test_dir, "qga.state", NULL);
112 g_unlink(tmp);
113 g_free(tmp);
115 tmp = g_build_filename(fixture->test_dir, "sock", NULL);
116 g_unlink(tmp);
117 g_free(tmp);
119 g_rmdir(fixture->test_dir);
120 g_free(fixture->test_dir);
123 static void qmp_assertion_message_error(const char *domain,
124 const char *file,
125 int line,
126 const char *func,
127 const char *expr,
128 QDict *dict)
130 const char *class, *desc;
131 char *s;
132 QDict *error;
134 error = qdict_get_qdict(dict, "error");
135 class = qdict_get_try_str(error, "class");
136 desc = qdict_get_try_str(error, "desc");
138 s = g_strdup_printf("assertion failed %s: %s %s", expr, class, desc);
139 g_assertion_message(domain, file, line, func, s);
140 g_free(s);
143 #define qmp_assert_no_error(err) do { \
144 if (qdict_haskey(err, "error")) { \
145 qmp_assertion_message_error(G_LOG_DOMAIN, __FILE__, __LINE__, \
146 G_STRFUNC, #err, err); \
148 } while (0)
150 static void test_qga_sync_delimited(gconstpointer fix)
152 const TestFixture *fixture = fix;
153 guint32 v, r = g_random_int();
154 unsigned char c;
155 QDict *ret;
156 gchar *cmd;
158 cmd = g_strdup_printf("%c{'execute': 'guest-sync-delimited',"
159 " 'arguments': {'id': %u } }", 0xff, r);
160 qmp_fd_send(fixture->fd, cmd);
161 g_free(cmd);
163 v = read(fixture->fd, &c, 1);
164 g_assert_cmpint(v, ==, 1);
165 g_assert_cmpint(c, ==, 0xff);
167 ret = qmp_fd_receive(fixture->fd);
168 g_assert_nonnull(ret);
169 qmp_assert_no_error(ret);
171 v = qdict_get_int(ret, "return");
172 g_assert_cmpint(r, ==, v);
174 QDECREF(ret);
177 static void test_qga_sync(gconstpointer fix)
179 const TestFixture *fixture = fix;
180 guint32 v, r = g_random_int();
181 QDict *ret;
182 gchar *cmd;
184 cmd = g_strdup_printf("%c{'execute': 'guest-sync',"
185 " 'arguments': {'id': %u } }", 0xff, r);
186 ret = qmp_fd(fixture->fd, cmd);
187 g_free(cmd);
189 g_assert_nonnull(ret);
190 qmp_assert_no_error(ret);
192 v = qdict_get_int(ret, "return");
193 g_assert_cmpint(r, ==, v);
195 QDECREF(ret);
198 static void test_qga_ping(gconstpointer fix)
200 const TestFixture *fixture = fix;
201 QDict *ret;
203 ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping'}");
204 g_assert_nonnull(ret);
205 qmp_assert_no_error(ret);
207 QDECREF(ret);
210 static void test_qga_invalid_cmd(gconstpointer fix)
212 const TestFixture *fixture = fix;
213 QDict *ret, *error;
214 const gchar *class, *desc;
216 ret = qmp_fd(fixture->fd, "{'execute': 'guest-invalid-cmd'}");
217 g_assert_nonnull(ret);
219 error = qdict_get_qdict(ret, "error");
220 class = qdict_get_try_str(error, "class");
221 desc = qdict_get_try_str(error, "desc");
223 g_assert_cmpstr(class, ==, "CommandNotFound");
224 g_assert_cmpint(strlen(desc), >, 0);
226 QDECREF(ret);
229 static void test_qga_info(gconstpointer fix)
231 const TestFixture *fixture = fix;
232 QDict *ret, *val;
233 const gchar *version;
235 ret = qmp_fd(fixture->fd, "{'execute': 'guest-info'}");
236 g_assert_nonnull(ret);
237 qmp_assert_no_error(ret);
239 val = qdict_get_qdict(ret, "return");
240 version = qdict_get_try_str(val, "version");
241 g_assert_cmpstr(version, ==, QEMU_VERSION);
243 QDECREF(ret);
246 static void test_qga_get_vcpus(gconstpointer fix)
248 const TestFixture *fixture = fix;
249 QDict *ret;
250 QList *list;
251 const QListEntry *entry;
253 ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-vcpus'}");
254 g_assert_nonnull(ret);
255 qmp_assert_no_error(ret);
257 /* check there is at least a cpu */
258 list = qdict_get_qlist(ret, "return");
259 entry = qlist_first(list);
260 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
261 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "logical-id"));
263 QDECREF(ret);
266 static void test_qga_get_fsinfo(gconstpointer fix)
268 const TestFixture *fixture = fix;
269 QDict *ret;
270 QList *list;
271 const QListEntry *entry;
273 ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-fsinfo'}");
274 g_assert_nonnull(ret);
275 qmp_assert_no_error(ret);
277 /* sanity-check the response if there are any filesystems */
278 list = qdict_get_qlist(ret, "return");
279 entry = qlist_first(list);
280 if (entry) {
281 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
282 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "mountpoint"));
283 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "type"));
284 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "disk"));
287 QDECREF(ret);
290 static void test_qga_get_memory_block_info(gconstpointer fix)
292 const TestFixture *fixture = fix;
293 QDict *ret, *val;
294 int64_t size;
296 ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-block-info'}");
297 g_assert_nonnull(ret);
299 /* some systems might not expose memory block info in sysfs */
300 if (!qdict_haskey(ret, "error")) {
301 /* check there is at least some memory */
302 val = qdict_get_qdict(ret, "return");
303 size = qdict_get_int(val, "size");
304 g_assert_cmpint(size, >, 0);
307 QDECREF(ret);
310 static void test_qga_get_memory_blocks(gconstpointer fix)
312 const TestFixture *fixture = fix;
313 QDict *ret;
314 QList *list;
315 const QListEntry *entry;
317 ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-blocks'}");
318 g_assert_nonnull(ret);
320 /* some systems might not expose memory block info in sysfs */
321 if (!qdict_haskey(ret, "error")) {
322 list = qdict_get_qlist(ret, "return");
323 entry = qlist_first(list);
324 /* newer versions of qga may return empty list without error */
325 if (entry) {
326 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "phys-index"));
327 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
331 QDECREF(ret);
334 static void test_qga_network_get_interfaces(gconstpointer fix)
336 const TestFixture *fixture = fix;
337 QDict *ret;
338 QList *list;
339 const QListEntry *entry;
341 ret = qmp_fd(fixture->fd, "{'execute': 'guest-network-get-interfaces'}");
342 g_assert_nonnull(ret);
343 qmp_assert_no_error(ret);
345 /* check there is at least an interface */
346 list = qdict_get_qlist(ret, "return");
347 entry = qlist_first(list);
348 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
350 QDECREF(ret);
353 static void test_qga_file_ops(gconstpointer fix)
355 const TestFixture *fixture = fix;
356 const unsigned char helloworld[] = "Hello World!\n";
357 const char *b64;
358 gchar *cmd, *path, *enc;
359 unsigned char *dec;
360 QDict *ret, *val;
361 int64_t id, eof;
362 gsize count;
363 FILE *f;
364 char tmp[100];
366 /* open */
367 ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
368 " 'arguments': { 'path': 'foo', 'mode': 'w+' } }");
369 g_assert_nonnull(ret);
370 qmp_assert_no_error(ret);
371 id = qdict_get_int(ret, "return");
372 QDECREF(ret);
374 enc = g_base64_encode(helloworld, sizeof(helloworld));
375 /* write */
376 cmd = g_strdup_printf("{'execute': 'guest-file-write',"
377 " 'arguments': { 'handle': %" PRId64 ","
378 " 'buf-b64': '%s' } }", id, enc);
379 ret = qmp_fd(fixture->fd, cmd);
380 g_assert_nonnull(ret);
381 qmp_assert_no_error(ret);
383 val = qdict_get_qdict(ret, "return");
384 count = qdict_get_int(val, "count");
385 eof = qdict_get_bool(val, "eof");
386 g_assert_cmpint(count, ==, sizeof(helloworld));
387 g_assert_cmpint(eof, ==, 0);
388 QDECREF(ret);
389 g_free(cmd);
391 /* flush */
392 cmd = g_strdup_printf("{'execute': 'guest-file-flush',"
393 " 'arguments': {'handle': %" PRId64 "} }",
394 id);
395 ret = qmp_fd(fixture->fd, cmd);
396 QDECREF(ret);
397 g_free(cmd);
399 /* close */
400 cmd = g_strdup_printf("{'execute': 'guest-file-close',"
401 " 'arguments': {'handle': %" PRId64 "} }",
402 id);
403 ret = qmp_fd(fixture->fd, cmd);
404 QDECREF(ret);
405 g_free(cmd);
407 /* check content */
408 path = g_build_filename(fixture->test_dir, "foo", NULL);
409 f = fopen(path, "r");
410 g_assert_nonnull(f);
411 count = fread(tmp, 1, sizeof(tmp), f);
412 g_assert_cmpint(count, ==, sizeof(helloworld));
413 tmp[count] = 0;
414 g_assert_cmpstr(tmp, ==, (char *)helloworld);
415 fclose(f);
417 /* open */
418 ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
419 " 'arguments': { 'path': 'foo', 'mode': 'r' } }");
420 g_assert_nonnull(ret);
421 qmp_assert_no_error(ret);
422 id = qdict_get_int(ret, "return");
423 QDECREF(ret);
425 /* read */
426 cmd = g_strdup_printf("{'execute': 'guest-file-read',"
427 " 'arguments': { 'handle': %" PRId64 "} }",
428 id);
429 ret = qmp_fd(fixture->fd, cmd);
430 val = qdict_get_qdict(ret, "return");
431 count = qdict_get_int(val, "count");
432 eof = qdict_get_bool(val, "eof");
433 b64 = qdict_get_str(val, "buf-b64");
434 g_assert_cmpint(count, ==, sizeof(helloworld));
435 g_assert(eof);
436 g_assert_cmpstr(b64, ==, enc);
438 QDECREF(ret);
439 g_free(cmd);
440 g_free(enc);
442 /* read eof */
443 cmd = g_strdup_printf("{'execute': 'guest-file-read',"
444 " 'arguments': { 'handle': %" PRId64 "} }",
445 id);
446 ret = qmp_fd(fixture->fd, cmd);
447 val = qdict_get_qdict(ret, "return");
448 count = qdict_get_int(val, "count");
449 eof = qdict_get_bool(val, "eof");
450 b64 = qdict_get_str(val, "buf-b64");
451 g_assert_cmpint(count, ==, 0);
452 g_assert(eof);
453 g_assert_cmpstr(b64, ==, "");
454 QDECREF(ret);
455 g_free(cmd);
457 /* seek */
458 cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
459 " 'arguments': { 'handle': %" PRId64 ", "
460 " 'offset': %d, 'whence': %d } }",
461 id, 6, QGA_SEEK_SET);
462 ret = qmp_fd(fixture->fd, cmd);
463 qmp_assert_no_error(ret);
464 val = qdict_get_qdict(ret, "return");
465 count = qdict_get_int(val, "position");
466 eof = qdict_get_bool(val, "eof");
467 g_assert_cmpint(count, ==, 6);
468 g_assert(!eof);
469 QDECREF(ret);
470 g_free(cmd);
472 /* partial read */
473 cmd = g_strdup_printf("{'execute': 'guest-file-read',"
474 " 'arguments': { 'handle': %" PRId64 "} }",
475 id);
476 ret = qmp_fd(fixture->fd, cmd);
477 val = qdict_get_qdict(ret, "return");
478 count = qdict_get_int(val, "count");
479 eof = qdict_get_bool(val, "eof");
480 b64 = qdict_get_str(val, "buf-b64");
481 g_assert_cmpint(count, ==, sizeof(helloworld) - 6);
482 g_assert(eof);
483 dec = g_base64_decode(b64, &count);
484 g_assert_cmpint(count, ==, sizeof(helloworld) - 6);
485 g_assert_cmpmem(dec, count, helloworld + 6, sizeof(helloworld) - 6);
486 g_free(dec);
488 QDECREF(ret);
489 g_free(cmd);
491 /* close */
492 cmd = g_strdup_printf("{'execute': 'guest-file-close',"
493 " 'arguments': {'handle': %" PRId64 "} }",
494 id);
495 ret = qmp_fd(fixture->fd, cmd);
496 QDECREF(ret);
497 g_free(cmd);
500 static void test_qga_file_write_read(gconstpointer fix)
502 const TestFixture *fixture = fix;
503 const unsigned char helloworld[] = "Hello World!\n";
504 const char *b64;
505 gchar *cmd, *enc;
506 QDict *ret, *val;
507 int64_t id, eof;
508 gsize count;
510 /* open */
511 ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
512 " 'arguments': { 'path': 'foo', 'mode': 'w+' } }");
513 g_assert_nonnull(ret);
514 qmp_assert_no_error(ret);
515 id = qdict_get_int(ret, "return");
516 QDECREF(ret);
518 enc = g_base64_encode(helloworld, sizeof(helloworld));
519 /* write */
520 cmd = g_strdup_printf("{'execute': 'guest-file-write',"
521 " 'arguments': { 'handle': %" PRId64 ","
522 " 'buf-b64': '%s' } }", id, enc);
523 ret = qmp_fd(fixture->fd, cmd);
524 g_assert_nonnull(ret);
525 qmp_assert_no_error(ret);
527 val = qdict_get_qdict(ret, "return");
528 count = qdict_get_int(val, "count");
529 eof = qdict_get_bool(val, "eof");
530 g_assert_cmpint(count, ==, sizeof(helloworld));
531 g_assert_cmpint(eof, ==, 0);
532 QDECREF(ret);
533 g_free(cmd);
535 /* read (check implicit flush) */
536 cmd = g_strdup_printf("{'execute': 'guest-file-read',"
537 " 'arguments': { 'handle': %" PRId64 "} }",
538 id);
539 ret = qmp_fd(fixture->fd, cmd);
540 val = qdict_get_qdict(ret, "return");
541 count = qdict_get_int(val, "count");
542 eof = qdict_get_bool(val, "eof");
543 b64 = qdict_get_str(val, "buf-b64");
544 g_assert_cmpint(count, ==, 0);
545 g_assert(eof);
546 g_assert_cmpstr(b64, ==, "");
547 QDECREF(ret);
548 g_free(cmd);
550 /* seek to 0 */
551 cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
552 " 'arguments': { 'handle': %" PRId64 ", "
553 " 'offset': %d, 'whence': %d } }",
554 id, 0, QGA_SEEK_SET);
555 ret = qmp_fd(fixture->fd, cmd);
556 qmp_assert_no_error(ret);
557 val = qdict_get_qdict(ret, "return");
558 count = qdict_get_int(val, "position");
559 eof = qdict_get_bool(val, "eof");
560 g_assert_cmpint(count, ==, 0);
561 g_assert(!eof);
562 QDECREF(ret);
563 g_free(cmd);
565 /* read */
566 cmd = g_strdup_printf("{'execute': 'guest-file-read',"
567 " 'arguments': { 'handle': %" PRId64 "} }",
568 id);
569 ret = qmp_fd(fixture->fd, cmd);
570 val = qdict_get_qdict(ret, "return");
571 count = qdict_get_int(val, "count");
572 eof = qdict_get_bool(val, "eof");
573 b64 = qdict_get_str(val, "buf-b64");
574 g_assert_cmpint(count, ==, sizeof(helloworld));
575 g_assert(eof);
576 g_assert_cmpstr(b64, ==, enc);
577 QDECREF(ret);
578 g_free(cmd);
579 g_free(enc);
581 /* close */
582 cmd = g_strdup_printf("{'execute': 'guest-file-close',"
583 " 'arguments': {'handle': %" PRId64 "} }",
584 id);
585 ret = qmp_fd(fixture->fd, cmd);
586 QDECREF(ret);
587 g_free(cmd);
590 static void test_qga_get_time(gconstpointer fix)
592 const TestFixture *fixture = fix;
593 QDict *ret;
594 int64_t time;
596 ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
597 g_assert_nonnull(ret);
598 qmp_assert_no_error(ret);
600 time = qdict_get_int(ret, "return");
601 g_assert_cmpint(time, >, 0);
603 QDECREF(ret);
606 static void test_qga_set_time(gconstpointer fix)
608 const TestFixture *fixture = fix;
609 QDict *ret;
610 int64_t current, time;
611 gchar *cmd;
613 /* get current time */
614 ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
615 g_assert_nonnull(ret);
616 qmp_assert_no_error(ret);
617 current = qdict_get_int(ret, "return");
618 g_assert_cmpint(current, >, 0);
619 QDECREF(ret);
621 /* set some old time */
622 ret = qmp_fd(fixture->fd, "{'execute': 'guest-set-time',"
623 " 'arguments': { 'time': 1000 } }");
624 g_assert_nonnull(ret);
625 qmp_assert_no_error(ret);
626 QDECREF(ret);
628 /* check old time */
629 ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
630 g_assert_nonnull(ret);
631 qmp_assert_no_error(ret);
632 time = qdict_get_int(ret, "return");
633 g_assert_cmpint(time / 1000, <, G_USEC_PER_SEC * 10);
634 QDECREF(ret);
636 /* set back current time */
637 cmd = g_strdup_printf("{'execute': 'guest-set-time',"
638 " 'arguments': { 'time': %" PRId64 " } }",
639 current + time * 1000);
640 ret = qmp_fd(fixture->fd, cmd);
641 g_free(cmd);
642 g_assert_nonnull(ret);
643 qmp_assert_no_error(ret);
644 QDECREF(ret);
647 static void test_qga_fstrim(gconstpointer fix)
649 const TestFixture *fixture = fix;
650 QDict *ret;
651 QList *list;
652 const QListEntry *entry;
654 ret = qmp_fd(fixture->fd, "{'execute': 'guest-fstrim',"
655 " arguments: { minimum: 4194304 } }");
656 g_assert_nonnull(ret);
657 qmp_assert_no_error(ret);
658 list = qdict_get_qlist(ret, "return");
659 entry = qlist_first(list);
660 g_assert(qdict_haskey(qobject_to_qdict(entry->value), "paths"));
662 QDECREF(ret);
665 static void test_qga_blacklist(gconstpointer data)
667 TestFixture fix;
668 QDict *ret, *error;
669 const gchar *class, *desc;
671 fixture_setup(&fix, "-b guest-ping,guest-get-time");
673 /* check blacklist */
674 ret = qmp_fd(fix.fd, "{'execute': 'guest-ping'}");
675 g_assert_nonnull(ret);
676 error = qdict_get_qdict(ret, "error");
677 class = qdict_get_try_str(error, "class");
678 desc = qdict_get_try_str(error, "desc");
679 g_assert_cmpstr(class, ==, "GenericError");
680 g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
681 QDECREF(ret);
683 ret = qmp_fd(fix.fd, "{'execute': 'guest-get-time'}");
684 g_assert_nonnull(ret);
685 error = qdict_get_qdict(ret, "error");
686 class = qdict_get_try_str(error, "class");
687 desc = qdict_get_try_str(error, "desc");
688 g_assert_cmpstr(class, ==, "GenericError");
689 g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
690 QDECREF(ret);
692 /* check something work */
693 ret = qmp_fd(fix.fd, "{'execute': 'guest-get-fsinfo'}");
694 qmp_assert_no_error(ret);
695 QDECREF(ret);
697 fixture_tear_down(&fix, NULL);
700 static void test_qga_config(gconstpointer data)
702 GError *error = NULL;
703 char *cwd, *cmd, *out, *err, *str, **strv, *conf, **argv = NULL;
704 char *env[2];
705 int status, tmp;
706 gsize n;
707 GKeyFile *kf;
708 const char *qga_config =
709 "[general]\n"
710 "daemon=false\n"
711 "method=virtio-serial\n"
712 "path=/path/to/org.qemu.guest_agent.0\n"
713 "pidfile=/var/foo/qemu-ga.pid\n"
714 "statedir=/var/state\n"
715 "verbose=true\n"
716 "blacklist=guest-ping;guest-get-time\n";
718 tmp = g_file_open_tmp(NULL, &conf, &error);
719 g_assert_no_error(error);
720 g_assert_cmpint(tmp, >=, 0);
721 g_assert_cmpstr(conf, !=, "");
723 g_file_set_contents(conf, qga_config, -1, &error);
724 g_assert_no_error(error);
726 cwd = g_get_current_dir();
727 cmd = g_strdup_printf("%s%cqemu-ga -D",
728 cwd, G_DIR_SEPARATOR);
729 g_shell_parse_argv(cmd, NULL, &argv, &error);
730 g_assert_no_error(error);
732 env[0] = g_strdup_printf("QGA_CONF=%s", conf);
733 env[1] = NULL;
734 g_spawn_sync(NULL, argv, env, 0,
735 NULL, NULL, &out, &err, &status, &error);
736 g_assert_no_error(error);
737 g_assert_cmpstr(err, ==, "");
738 g_assert_cmpint(status, ==, 0);
740 kf = g_key_file_new();
741 g_key_file_load_from_data(kf, out, -1, G_KEY_FILE_NONE, &error);
742 g_assert_no_error(error);
744 str = g_key_file_get_start_group(kf);
745 g_assert_cmpstr(str, ==, "general");
746 g_free(str);
748 g_assert_false(g_key_file_get_boolean(kf, "general", "daemon", &error));
749 g_assert_no_error(error);
751 str = g_key_file_get_string(kf, "general", "method", &error);
752 g_assert_no_error(error);
753 g_assert_cmpstr(str, ==, "virtio-serial");
754 g_free(str);
756 str = g_key_file_get_string(kf, "general", "path", &error);
757 g_assert_no_error(error);
758 g_assert_cmpstr(str, ==, "/path/to/org.qemu.guest_agent.0");
759 g_free(str);
761 str = g_key_file_get_string(kf, "general", "pidfile", &error);
762 g_assert_no_error(error);
763 g_assert_cmpstr(str, ==, "/var/foo/qemu-ga.pid");
764 g_free(str);
766 str = g_key_file_get_string(kf, "general", "statedir", &error);
767 g_assert_no_error(error);
768 g_assert_cmpstr(str, ==, "/var/state");
769 g_free(str);
771 g_assert_true(g_key_file_get_boolean(kf, "general", "verbose", &error));
772 g_assert_no_error(error);
774 strv = g_key_file_get_string_list(kf, "general", "blacklist", &n, &error);
775 g_assert_cmpint(n, ==, 2);
776 #if GLIB_CHECK_VERSION(2, 44, 0)
777 g_assert_true(g_strv_contains((const char * const *)strv,
778 "guest-ping"));
779 g_assert_true(g_strv_contains((const char * const *)strv,
780 "guest-get-time"));
781 #endif
782 g_assert_no_error(error);
783 g_strfreev(strv);
785 g_free(out);
786 g_free(err);
787 g_free(conf);
788 g_free(env[0]);
789 g_key_file_free(kf);
791 close(tmp);
794 static void test_qga_fsfreeze_status(gconstpointer fix)
796 const TestFixture *fixture = fix;
797 QDict *ret;
798 const gchar *status;
800 ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}");
801 g_assert_nonnull(ret);
802 qmp_assert_no_error(ret);
804 status = qdict_get_try_str(ret, "return");
805 g_assert_cmpstr(status, ==, "thawed");
807 QDECREF(ret);
810 static void test_qga_fsfreeze_and_thaw(gconstpointer fix)
812 const TestFixture *fixture = fix;
813 QDict *ret;
814 const gchar *status;
816 ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-freeze'}");
817 g_assert_nonnull(ret);
818 qmp_assert_no_error(ret);
819 QDECREF(ret);
821 ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}");
822 g_assert_nonnull(ret);
823 qmp_assert_no_error(ret);
824 status = qdict_get_try_str(ret, "return");
825 g_assert_cmpstr(status, ==, "frozen");
826 QDECREF(ret);
828 ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-thaw'}");
829 g_assert_nonnull(ret);
830 qmp_assert_no_error(ret);
831 QDECREF(ret);
834 int main(int argc, char **argv)
836 TestFixture fix;
837 int ret;
839 setlocale (LC_ALL, "");
840 g_test_init(&argc, &argv, NULL);
841 fixture_setup(&fix, NULL);
843 g_test_add_data_func("/qga/sync-delimited", &fix, test_qga_sync_delimited);
844 g_test_add_data_func("/qga/sync", &fix, test_qga_sync);
845 g_test_add_data_func("/qga/ping", &fix, test_qga_ping);
846 g_test_add_data_func("/qga/info", &fix, test_qga_info);
847 g_test_add_data_func("/qga/network-get-interfaces", &fix,
848 test_qga_network_get_interfaces);
849 g_test_add_data_func("/qga/get-vcpus", &fix, test_qga_get_vcpus);
850 g_test_add_data_func("/qga/get-fsinfo", &fix, test_qga_get_fsinfo);
851 g_test_add_data_func("/qga/get-memory-block-info", &fix,
852 test_qga_get_memory_block_info);
853 g_test_add_data_func("/qga/get-memory-blocks", &fix,
854 test_qga_get_memory_blocks);
855 g_test_add_data_func("/qga/file-ops", &fix, test_qga_file_ops);
856 g_test_add_data_func("/qga/file-write-read", &fix, test_qga_file_write_read);
857 g_test_add_data_func("/qga/get-time", &fix, test_qga_get_time);
858 g_test_add_data_func("/qga/invalid-cmd", &fix, test_qga_invalid_cmd);
859 g_test_add_data_func("/qga/fsfreeze-status", &fix,
860 test_qga_fsfreeze_status);
862 g_test_add_data_func("/qga/blacklist", NULL, test_qga_blacklist);
863 g_test_add_data_func("/qga/config", NULL, test_qga_config);
865 if (g_getenv("QGA_TEST_SIDE_EFFECTING")) {
866 g_test_add_data_func("/qga/fsfreeze-and-thaw", &fix,
867 test_qga_fsfreeze_and_thaw);
868 g_test_add_data_func("/qga/set-time", &fix, test_qga_set_time);
869 g_test_add_data_func("/qga/fstrim", &fix, test_qga_fstrim);
872 ret = g_test_run();
874 fixture_tear_down(&fix, NULL);
876 return ret;