1681c28a3SPeter Maydell #include "qemu/osdep.h" 262c39b30SMarc-André Lureau #include <locale.h> 362c39b30SMarc-André Lureau #include <glib/gstdio.h> 462c39b30SMarc-André Lureau #include <sys/socket.h> 562c39b30SMarc-André Lureau #include <sys/un.h> 662c39b30SMarc-André Lureau 7907b5105SMarc-André Lureau #include "../qtest/libqtest.h" 8452fcdbcSMarkus Armbruster #include "qapi/qmp/qdict.h" 947e6b297SMarkus Armbruster #include "qapi/qmp/qlist.h" 1062c39b30SMarc-André Lureau 1162c39b30SMarc-André Lureau typedef struct { 1262c39b30SMarc-André Lureau char *test_dir; 1362c39b30SMarc-André Lureau GMainLoop *loop; 1462c39b30SMarc-André Lureau int fd; 1562c39b30SMarc-André Lureau GPid pid; 1662c39b30SMarc-André Lureau } TestFixture; 1762c39b30SMarc-André Lureau 1862c39b30SMarc-André Lureau static int connect_qga(char *path) 1962c39b30SMarc-André Lureau { 2062c39b30SMarc-André Lureau int s, ret, len, i = 0; 2162c39b30SMarc-André Lureau struct sockaddr_un remote; 2262c39b30SMarc-André Lureau 2362c39b30SMarc-André Lureau s = socket(AF_UNIX, SOCK_STREAM, 0); 2462c39b30SMarc-André Lureau g_assert(s != -1); 2562c39b30SMarc-André Lureau 2662c39b30SMarc-André Lureau remote.sun_family = AF_UNIX; 2762c39b30SMarc-André Lureau do { 2862c39b30SMarc-André Lureau strcpy(remote.sun_path, path); 2962c39b30SMarc-André Lureau len = strlen(remote.sun_path) + sizeof(remote.sun_family); 3062c39b30SMarc-André Lureau ret = connect(s, (struct sockaddr *)&remote, len); 3162c39b30SMarc-André Lureau if (ret == -1) { 3262c39b30SMarc-André Lureau g_usleep(G_USEC_PER_SEC); 3362c39b30SMarc-André Lureau } 3462c39b30SMarc-André Lureau if (i++ == 10) { 355dc51100SPaolo Bonzini close(s); 3662c39b30SMarc-André Lureau return -1; 3762c39b30SMarc-André Lureau } 3862c39b30SMarc-André Lureau } while (ret == -1); 3962c39b30SMarc-André Lureau 4062c39b30SMarc-André Lureau return s; 4162c39b30SMarc-André Lureau } 4262c39b30SMarc-André Lureau 4362c39b30SMarc-André Lureau static void qga_watch(GPid pid, gint status, gpointer user_data) 4462c39b30SMarc-André Lureau { 4562c39b30SMarc-André Lureau TestFixture *fixture = user_data; 4662c39b30SMarc-André Lureau 4762c39b30SMarc-André Lureau g_assert_cmpint(status, ==, 0); 4862c39b30SMarc-André Lureau g_main_loop_quit(fixture->loop); 4962c39b30SMarc-André Lureau } 5062c39b30SMarc-André Lureau 5162c39b30SMarc-André Lureau static void 52c28afa76STomáš Golembiovský fixture_setup(TestFixture *fixture, gconstpointer data, gchar **envp) 5362c39b30SMarc-André Lureau { 5462c39b30SMarc-André Lureau const gchar *extra_arg = data; 5562c39b30SMarc-André Lureau 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; 6062c39b30SMarc-André Lureau 6162c39b30SMarc-André Lureau fixture->loop = g_main_loop_new(NULL, FALSE); 6262c39b30SMarc-André Lureau 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)); 6562c39b30SMarc-André Lureau 6662c39b30SMarc-André Lureau path = g_build_filename(fixture->test_dir, "sock", NULL); 6762c39b30SMarc-André Lureau cwd = g_get_current_dir(); 68f15bff25SPaolo Bonzini cmd = g_strdup_printf("%s%cqga%cqemu-ga -m unix-listen -t %s -p %s %s %s", 69f15bff25SPaolo Bonzini cwd, G_DIR_SEPARATOR, G_DIR_SEPARATOR, 7062c39b30SMarc-André Lureau fixture->test_dir, path, 7162c39b30SMarc-André Lureau getenv("QTEST_LOG") ? "-v" : "", 7262c39b30SMarc-André Lureau extra_arg ?: ""); 7362c39b30SMarc-André Lureau g_shell_parse_argv(cmd, NULL, &argv, &error); 7462c39b30SMarc-André Lureau g_assert_no_error(error); 7562c39b30SMarc-André Lureau 76c28afa76STomáš Golembiovský g_spawn_async(fixture->test_dir, argv, envp, 7762c39b30SMarc-André Lureau G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, 7862c39b30SMarc-André Lureau NULL, NULL, &fixture->pid, &error); 7962c39b30SMarc-André Lureau g_assert_no_error(error); 8062c39b30SMarc-André Lureau 8162c39b30SMarc-André Lureau g_child_watch_add(fixture->pid, qga_watch, fixture); 8262c39b30SMarc-André Lureau 8362c39b30SMarc-André Lureau fixture->fd = connect_qga(path); 8462c39b30SMarc-André Lureau g_assert_cmpint(fixture->fd, !=, -1); 8562c39b30SMarc-André Lureau } 8662c39b30SMarc-André Lureau 8762c39b30SMarc-André Lureau static void 8862c39b30SMarc-André Lureau fixture_tear_down(TestFixture *fixture, gconstpointer data) 8962c39b30SMarc-André Lureau { 90bb6960a1SMarc-André Lureau g_autofree char *tmp = NULL; 9162c39b30SMarc-André Lureau 9262c39b30SMarc-André Lureau kill(fixture->pid, SIGTERM); 9362c39b30SMarc-André Lureau 9462c39b30SMarc-André Lureau g_main_loop_run(fixture->loop); 9562c39b30SMarc-André Lureau g_main_loop_unref(fixture->loop); 9662c39b30SMarc-André Lureau 9762c39b30SMarc-André Lureau g_spawn_close_pid(fixture->pid); 9862c39b30SMarc-André Lureau 9962c39b30SMarc-André Lureau tmp = g_build_filename(fixture->test_dir, "foo", NULL); 10062c39b30SMarc-André Lureau g_unlink(tmp); 10162c39b30SMarc-André Lureau g_free(tmp); 10262c39b30SMarc-André Lureau 10362c39b30SMarc-André Lureau tmp = g_build_filename(fixture->test_dir, "qga.state", NULL); 10462c39b30SMarc-André Lureau g_unlink(tmp); 10562c39b30SMarc-André Lureau g_free(tmp); 10662c39b30SMarc-André Lureau 10762c39b30SMarc-André Lureau tmp = g_build_filename(fixture->test_dir, "sock", NULL); 10862c39b30SMarc-André Lureau g_unlink(tmp); 10962c39b30SMarc-André Lureau 11062c39b30SMarc-André Lureau g_rmdir(fixture->test_dir); 11162c39b30SMarc-André Lureau g_free(fixture->test_dir); 11243d1da7cSAlex Chen close(fixture->fd); 11362c39b30SMarc-André Lureau } 11462c39b30SMarc-André Lureau 11562c39b30SMarc-André Lureau static void qmp_assertion_message_error(const char *domain, 11662c39b30SMarc-André Lureau const char *file, 11762c39b30SMarc-André Lureau int line, 11862c39b30SMarc-André Lureau const char *func, 11962c39b30SMarc-André Lureau const char *expr, 12062c39b30SMarc-André Lureau QDict *dict) 12162c39b30SMarc-André Lureau { 12262c39b30SMarc-André Lureau const char *class, *desc; 123bb6960a1SMarc-André Lureau g_autofree char *s = NULL; 12462c39b30SMarc-André Lureau QDict *error; 12562c39b30SMarc-André Lureau 12662c39b30SMarc-André Lureau error = qdict_get_qdict(dict, "error"); 12762c39b30SMarc-André Lureau class = qdict_get_try_str(error, "class"); 12862c39b30SMarc-André Lureau desc = qdict_get_try_str(error, "desc"); 12962c39b30SMarc-André Lureau 13062c39b30SMarc-André Lureau s = g_strdup_printf("assertion failed %s: %s %s", expr, class, desc); 13162c39b30SMarc-André Lureau g_assertion_message(domain, file, line, func, s); 13262c39b30SMarc-André Lureau } 13362c39b30SMarc-André Lureau 13462c39b30SMarc-André Lureau #define qmp_assert_no_error(err) do { \ 13562c39b30SMarc-André Lureau if (qdict_haskey(err, "error")) { \ 13662c39b30SMarc-André Lureau qmp_assertion_message_error(G_LOG_DOMAIN, __FILE__, __LINE__, \ 13762c39b30SMarc-André Lureau G_STRFUNC, #err, err); \ 13862c39b30SMarc-André Lureau } \ 13962c39b30SMarc-André Lureau } while (0) 14062c39b30SMarc-André Lureau 14162c39b30SMarc-André Lureau static void test_qga_sync_delimited(gconstpointer fix) 14262c39b30SMarc-André Lureau { 14362c39b30SMarc-André Lureau const TestFixture *fixture = fix; 1440f555602SPaolo Bonzini guint32 v, r = g_test_rand_int(); 14562c39b30SMarc-André Lureau unsigned char c; 146bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 14762c39b30SMarc-André Lureau 148e2f64a68SMarkus Armbruster qmp_fd_send_raw(fixture->fd, "\xff"); 149015715f5SMarkus Armbruster qmp_fd_send(fixture->fd, 150e2f64a68SMarkus Armbruster "{'execute': 'guest-sync-delimited'," 151015715f5SMarkus Armbruster " 'arguments': {'id': %u } }", 152015715f5SMarkus Armbruster r); 15362c39b30SMarc-André Lureau 1545229564bSEric Blake /* 1555229564bSEric Blake * Read and ignore garbage until resynchronized. 1565229564bSEric Blake * 1575229564bSEric Blake * Note that the full reset sequence would involve checking the 1585229564bSEric Blake * response of guest-sync-delimited and repeating the loop if 1595229564bSEric Blake * 'id' field of the response does not match the 'id' field of 1605229564bSEric Blake * the request. Testing this fully would require inserting 1615229564bSEric Blake * garbage in the response stream and is left as a future test 1625229564bSEric Blake * to implement. 1635229564bSEric Blake * 1645229564bSEric Blake * TODO: The server shouldn't emit so much garbage (among other 1655229564bSEric Blake * things, it loudly complains about the client's \xff being 1665229564bSEric Blake * invalid JSON, even though it is a documented part of the 1675229564bSEric Blake * handshake. 1685229564bSEric Blake */ 1695229564bSEric Blake do { 17062c39b30SMarc-André Lureau v = read(fixture->fd, &c, 1); 17162c39b30SMarc-André Lureau g_assert_cmpint(v, ==, 1); 1725229564bSEric Blake } while (c != 0xff); 17362c39b30SMarc-André Lureau 17462c39b30SMarc-André Lureau ret = qmp_fd_receive(fixture->fd); 17562c39b30SMarc-André Lureau g_assert_nonnull(ret); 17662c39b30SMarc-André Lureau qmp_assert_no_error(ret); 17762c39b30SMarc-André Lureau 17862c39b30SMarc-André Lureau v = qdict_get_int(ret, "return"); 17962c39b30SMarc-André Lureau g_assert_cmpint(r, ==, v); 18062c39b30SMarc-André Lureau } 18162c39b30SMarc-André Lureau 18262c39b30SMarc-André Lureau static void test_qga_sync(gconstpointer fix) 18362c39b30SMarc-André Lureau { 18462c39b30SMarc-André Lureau const TestFixture *fixture = fix; 1850f555602SPaolo Bonzini guint32 v, r = g_test_rand_int(); 186bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 18762c39b30SMarc-André Lureau 1885229564bSEric Blake /* 1895229564bSEric Blake * TODO guest-sync is inherently limited: we cannot distinguish 1905229564bSEric Blake * failure caused by reacting to garbage on the wire prior to this 1915229564bSEric Blake * command, from failure of this actual command. Clients are 1925229564bSEric Blake * supposed to be able to send a raw '\xff' byte to at least 1935229564bSEric Blake * re-synchronize the server's parser prior to this command, but 1945229564bSEric Blake * we are not in a position to test that here because (at least 1955229564bSEric Blake * for now) it causes the server to issue an error message about 1965229564bSEric Blake * invalid JSON. Testing of '\xff' handling is done in 1975229564bSEric Blake * guest-sync-delimited instead. 1985229564bSEric Blake */ 199015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 200015715f5SMarkus Armbruster "{'execute': 'guest-sync', 'arguments': {'id': %u } }", 201015715f5SMarkus Armbruster r); 20262c39b30SMarc-André Lureau 20362c39b30SMarc-André Lureau g_assert_nonnull(ret); 20462c39b30SMarc-André Lureau qmp_assert_no_error(ret); 20562c39b30SMarc-André Lureau 20662c39b30SMarc-André Lureau v = qdict_get_int(ret, "return"); 20762c39b30SMarc-André Lureau g_assert_cmpint(r, ==, v); 20862c39b30SMarc-André Lureau } 20962c39b30SMarc-André Lureau 21062c39b30SMarc-André Lureau static void test_qga_ping(gconstpointer fix) 21162c39b30SMarc-André Lureau { 21262c39b30SMarc-André Lureau const TestFixture *fixture = fix; 213bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 21462c39b30SMarc-André Lureau 21562c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping'}"); 21662c39b30SMarc-André Lureau g_assert_nonnull(ret); 21762c39b30SMarc-André Lureau qmp_assert_no_error(ret); 21862c39b30SMarc-André Lureau } 21962c39b30SMarc-André Lureau 2204eaca8deSMarc-André Lureau static void test_qga_id(gconstpointer fix) 221b5f84310SMarkus Armbruster { 222b5f84310SMarkus Armbruster const TestFixture *fixture = fix; 223bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 224b5f84310SMarkus Armbruster 225b5f84310SMarkus Armbruster ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping', 'id': 1}"); 226b5f84310SMarkus Armbruster g_assert_nonnull(ret); 2274eaca8deSMarc-André Lureau qmp_assert_no_error(ret); 2284eaca8deSMarc-André Lureau g_assert_cmpint(qdict_get_int(ret, "id"), ==, 1); 229b5f84310SMarkus Armbruster } 230b5f84310SMarkus Armbruster 231d4d7ed73SMarkus Armbruster static void test_qga_invalid_oob(gconstpointer fix) 232d4d7ed73SMarkus Armbruster { 233d4d7ed73SMarkus Armbruster const TestFixture *fixture = fix; 234ebb4d82dSMarc-André Lureau QDict *ret; 235d4d7ed73SMarkus Armbruster 23600ecec15SMarkus Armbruster ret = qmp_fd(fixture->fd, "{'exec-oob': 'guest-ping'}"); 237d4d7ed73SMarkus Armbruster g_assert_nonnull(ret); 238d4d7ed73SMarkus Armbruster 2393bc1b8eeSMarkus Armbruster qmp_expect_error_and_unref(ret, "GenericError"); 240d4d7ed73SMarkus Armbruster } 241d4d7ed73SMarkus Armbruster 2424bdadd86SMarc-André Lureau static void test_qga_invalid_args(gconstpointer fix) 2434bdadd86SMarc-André Lureau { 2444bdadd86SMarc-André Lureau const TestFixture *fixture = fix; 245bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 246bb6960a1SMarc-André Lureau QDict *error; 2474bdadd86SMarc-André Lureau const gchar *class, *desc; 2484bdadd86SMarc-André Lureau 2494bdadd86SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping', " 2504bdadd86SMarc-André Lureau "'arguments': {'foo': 42 }}"); 2514bdadd86SMarc-André Lureau g_assert_nonnull(ret); 2524bdadd86SMarc-André Lureau 2534bdadd86SMarc-André Lureau error = qdict_get_qdict(ret, "error"); 2544bdadd86SMarc-André Lureau class = qdict_get_try_str(error, "class"); 2554bdadd86SMarc-André Lureau desc = qdict_get_try_str(error, "desc"); 2564bdadd86SMarc-André Lureau 2574bdadd86SMarc-André Lureau g_assert_cmpstr(class, ==, "GenericError"); 258910f738bSMarkus Armbruster g_assert_cmpstr(desc, ==, "Parameter 'foo' is unexpected"); 2594bdadd86SMarc-André Lureau } 2604bdadd86SMarc-André Lureau 26162c39b30SMarc-André Lureau static void test_qga_invalid_cmd(gconstpointer fix) 26262c39b30SMarc-André Lureau { 26362c39b30SMarc-André Lureau const TestFixture *fixture = fix; 264bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 265bb6960a1SMarc-André Lureau QDict *error; 26662c39b30SMarc-André Lureau const gchar *class, *desc; 26762c39b30SMarc-André Lureau 26862c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-invalid-cmd'}"); 26962c39b30SMarc-André Lureau g_assert_nonnull(ret); 27062c39b30SMarc-André Lureau 27162c39b30SMarc-André Lureau error = qdict_get_qdict(ret, "error"); 27262c39b30SMarc-André Lureau class = qdict_get_try_str(error, "class"); 27362c39b30SMarc-André Lureau desc = qdict_get_try_str(error, "desc"); 27462c39b30SMarc-André Lureau 27562c39b30SMarc-André Lureau g_assert_cmpstr(class, ==, "CommandNotFound"); 27662c39b30SMarc-André Lureau g_assert_cmpint(strlen(desc), >, 0); 27762c39b30SMarc-André Lureau } 27862c39b30SMarc-André Lureau 27962c39b30SMarc-André Lureau static void test_qga_info(gconstpointer fix) 28062c39b30SMarc-André Lureau { 28162c39b30SMarc-André Lureau const TestFixture *fixture = fix; 282bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 283bb6960a1SMarc-André Lureau QDict *val; 28462c39b30SMarc-André Lureau const gchar *version; 28562c39b30SMarc-André Lureau 28662c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-info'}"); 28762c39b30SMarc-André Lureau g_assert_nonnull(ret); 28862c39b30SMarc-André Lureau qmp_assert_no_error(ret); 28962c39b30SMarc-André Lureau 29062c39b30SMarc-André Lureau val = qdict_get_qdict(ret, "return"); 29162c39b30SMarc-André Lureau version = qdict_get_try_str(val, "version"); 29262c39b30SMarc-André Lureau g_assert_cmpstr(version, ==, QEMU_VERSION); 29362c39b30SMarc-André Lureau } 29462c39b30SMarc-André Lureau 29562c39b30SMarc-André Lureau static void test_qga_get_vcpus(gconstpointer fix) 29662c39b30SMarc-André Lureau { 29762c39b30SMarc-André Lureau const TestFixture *fixture = fix; 298bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 29962c39b30SMarc-André Lureau QList *list; 30062c39b30SMarc-André Lureau const QListEntry *entry; 30162c39b30SMarc-André Lureau 30262c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-vcpus'}"); 30362c39b30SMarc-André Lureau g_assert_nonnull(ret); 30462c39b30SMarc-André Lureau qmp_assert_no_error(ret); 30562c39b30SMarc-André Lureau 30662c39b30SMarc-André Lureau /* check there is at least a cpu */ 30762c39b30SMarc-André Lureau list = qdict_get_qlist(ret, "return"); 30862c39b30SMarc-André Lureau entry = qlist_first(list); 3097dc847ebSMax Reitz g_assert(qdict_haskey(qobject_to(QDict, entry->value), "online")); 3107dc847ebSMax Reitz g_assert(qdict_haskey(qobject_to(QDict, entry->value), "logical-id")); 31162c39b30SMarc-André Lureau } 31262c39b30SMarc-André Lureau 31362c39b30SMarc-André Lureau static void test_qga_get_fsinfo(gconstpointer fix) 31462c39b30SMarc-André Lureau { 31562c39b30SMarc-André Lureau const TestFixture *fixture = fix; 316bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 31762c39b30SMarc-André Lureau QList *list; 31862c39b30SMarc-André Lureau const QListEntry *entry; 31962c39b30SMarc-André Lureau 32062c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-fsinfo'}"); 32162c39b30SMarc-André Lureau g_assert_nonnull(ret); 32262c39b30SMarc-André Lureau qmp_assert_no_error(ret); 32362c39b30SMarc-André Lureau 324b3e9e584SMichael Roth /* sanity-check the response if there are any filesystems */ 32562c39b30SMarc-André Lureau list = qdict_get_qlist(ret, "return"); 32662c39b30SMarc-André Lureau entry = qlist_first(list); 327b3e9e584SMichael Roth if (entry) { 3287dc847ebSMax Reitz g_assert(qdict_haskey(qobject_to(QDict, entry->value), "name")); 3297dc847ebSMax Reitz g_assert(qdict_haskey(qobject_to(QDict, entry->value), "mountpoint")); 3307dc847ebSMax Reitz g_assert(qdict_haskey(qobject_to(QDict, entry->value), "type")); 3317dc847ebSMax Reitz g_assert(qdict_haskey(qobject_to(QDict, entry->value), "disk")); 332b3e9e584SMichael Roth } 33362c39b30SMarc-André Lureau } 33462c39b30SMarc-André Lureau 33562c39b30SMarc-André Lureau static void test_qga_get_memory_block_info(gconstpointer fix) 33662c39b30SMarc-André Lureau { 33762c39b30SMarc-André Lureau const TestFixture *fixture = fix; 338bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 339bb6960a1SMarc-André Lureau QDict *val; 34062c39b30SMarc-André Lureau int64_t size; 34162c39b30SMarc-André Lureau 34262c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-block-info'}"); 34362c39b30SMarc-André Lureau g_assert_nonnull(ret); 34462c39b30SMarc-André Lureau 34562c39b30SMarc-André Lureau /* some systems might not expose memory block info in sysfs */ 34662c39b30SMarc-André Lureau if (!qdict_haskey(ret, "error")) { 34762c39b30SMarc-André Lureau /* check there is at least some memory */ 34862c39b30SMarc-André Lureau val = qdict_get_qdict(ret, "return"); 34962c39b30SMarc-André Lureau size = qdict_get_int(val, "size"); 35062c39b30SMarc-André Lureau g_assert_cmpint(size, >, 0); 35162c39b30SMarc-André Lureau } 35262c39b30SMarc-André Lureau } 35362c39b30SMarc-André Lureau 35462c39b30SMarc-André Lureau static void test_qga_get_memory_blocks(gconstpointer fix) 35562c39b30SMarc-André Lureau { 35662c39b30SMarc-André Lureau const TestFixture *fixture = fix; 357bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 35862c39b30SMarc-André Lureau QList *list; 35962c39b30SMarc-André Lureau const QListEntry *entry; 36062c39b30SMarc-André Lureau 36162c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-blocks'}"); 36262c39b30SMarc-André Lureau g_assert_nonnull(ret); 36362c39b30SMarc-André Lureau 36462c39b30SMarc-André Lureau /* some systems might not expose memory block info in sysfs */ 36562c39b30SMarc-André Lureau if (!qdict_haskey(ret, "error")) { 36662c39b30SMarc-André Lureau list = qdict_get_qlist(ret, "return"); 36762c39b30SMarc-André Lureau entry = qlist_first(list); 36862c39b30SMarc-André Lureau /* newer versions of qga may return empty list without error */ 36962c39b30SMarc-André Lureau if (entry) { 3707dc847ebSMax Reitz g_assert(qdict_haskey(qobject_to(QDict, entry->value), 3717dc847ebSMax Reitz "phys-index")); 3727dc847ebSMax Reitz g_assert(qdict_haskey(qobject_to(QDict, entry->value), "online")); 37362c39b30SMarc-André Lureau } 37462c39b30SMarc-André Lureau } 37562c39b30SMarc-André Lureau } 37662c39b30SMarc-André Lureau 37762c39b30SMarc-André Lureau static void test_qga_network_get_interfaces(gconstpointer fix) 37862c39b30SMarc-André Lureau { 37962c39b30SMarc-André Lureau const TestFixture *fixture = fix; 380bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 38162c39b30SMarc-André Lureau QList *list; 38262c39b30SMarc-André Lureau const QListEntry *entry; 38362c39b30SMarc-André Lureau 38462c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-network-get-interfaces'}"); 38562c39b30SMarc-André Lureau g_assert_nonnull(ret); 38662c39b30SMarc-André Lureau qmp_assert_no_error(ret); 38762c39b30SMarc-André Lureau 38862c39b30SMarc-André Lureau /* check there is at least an interface */ 38962c39b30SMarc-André Lureau list = qdict_get_qlist(ret, "return"); 39062c39b30SMarc-André Lureau entry = qlist_first(list); 3917dc847ebSMax Reitz g_assert(qdict_haskey(qobject_to(QDict, entry->value), "name")); 39262c39b30SMarc-André Lureau } 39362c39b30SMarc-André Lureau 39462c39b30SMarc-André Lureau static void test_qga_file_ops(gconstpointer fix) 39562c39b30SMarc-André Lureau { 39662c39b30SMarc-André Lureau const TestFixture *fixture = fix; 3974eaab85cSMarc-André Lureau const unsigned char helloworld[] = "Hello World!\n"; 39862c39b30SMarc-André Lureau const char *b64; 399015715f5SMarkus Armbruster gchar *path, *enc; 4004eaab85cSMarc-André Lureau unsigned char *dec; 40162c39b30SMarc-André Lureau QDict *ret, *val; 40262c39b30SMarc-André Lureau int64_t id, eof; 40362c39b30SMarc-André Lureau gsize count; 40462c39b30SMarc-André Lureau FILE *f; 40562c39b30SMarc-André Lureau char tmp[100]; 40662c39b30SMarc-André Lureau 40762c39b30SMarc-André Lureau /* open */ 40862c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open'," 40962c39b30SMarc-André Lureau " 'arguments': { 'path': 'foo', 'mode': 'w+' } }"); 41062c39b30SMarc-André Lureau g_assert_nonnull(ret); 41162c39b30SMarc-André Lureau qmp_assert_no_error(ret); 41262c39b30SMarc-André Lureau id = qdict_get_int(ret, "return"); 413cb3e7f08SMarc-André Lureau qobject_unref(ret); 41462c39b30SMarc-André Lureau 41562c39b30SMarc-André Lureau enc = g_base64_encode(helloworld, sizeof(helloworld)); 41662c39b30SMarc-André Lureau /* write */ 417015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 418015715f5SMarkus Armbruster "{'execute': 'guest-file-write'," 419015715f5SMarkus Armbruster " 'arguments': { 'handle': %" PRId64 ", 'buf-b64': %s } }", 420015715f5SMarkus Armbruster id, enc); 42162c39b30SMarc-André Lureau g_assert_nonnull(ret); 42262c39b30SMarc-André Lureau qmp_assert_no_error(ret); 42362c39b30SMarc-André Lureau 42462c39b30SMarc-André Lureau val = qdict_get_qdict(ret, "return"); 42562c39b30SMarc-André Lureau count = qdict_get_int(val, "count"); 42662c39b30SMarc-André Lureau eof = qdict_get_bool(val, "eof"); 42762c39b30SMarc-André Lureau g_assert_cmpint(count, ==, sizeof(helloworld)); 42862c39b30SMarc-André Lureau g_assert_cmpint(eof, ==, 0); 429cb3e7f08SMarc-André Lureau qobject_unref(ret); 43062c39b30SMarc-André Lureau 43162c39b30SMarc-André Lureau /* flush */ 432015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 433015715f5SMarkus Armbruster "{'execute': 'guest-file-flush'," 43462c39b30SMarc-André Lureau " 'arguments': {'handle': %" PRId64 "} }", 43562c39b30SMarc-André Lureau id); 436cb3e7f08SMarc-André Lureau qobject_unref(ret); 43762c39b30SMarc-André Lureau 43862c39b30SMarc-André Lureau /* close */ 439015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 440015715f5SMarkus Armbruster "{'execute': 'guest-file-close'," 44162c39b30SMarc-André Lureau " 'arguments': {'handle': %" PRId64 "} }", 44262c39b30SMarc-André Lureau id); 443cb3e7f08SMarc-André Lureau qobject_unref(ret); 44462c39b30SMarc-André Lureau 44562c39b30SMarc-André Lureau /* check content */ 44662c39b30SMarc-André Lureau path = g_build_filename(fixture->test_dir, "foo", NULL); 44762c39b30SMarc-André Lureau f = fopen(path, "r"); 4481e271338SMarc-André Lureau g_free(path); 44962c39b30SMarc-André Lureau g_assert_nonnull(f); 45062c39b30SMarc-André Lureau count = fread(tmp, 1, sizeof(tmp), f); 45162c39b30SMarc-André Lureau g_assert_cmpint(count, ==, sizeof(helloworld)); 45262c39b30SMarc-André Lureau tmp[count] = 0; 45362c39b30SMarc-André Lureau g_assert_cmpstr(tmp, ==, (char *)helloworld); 45462c39b30SMarc-André Lureau fclose(f); 45562c39b30SMarc-André Lureau 45662c39b30SMarc-André Lureau /* open */ 45762c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open'," 45862c39b30SMarc-André Lureau " 'arguments': { 'path': 'foo', 'mode': 'r' } }"); 45962c39b30SMarc-André Lureau g_assert_nonnull(ret); 46062c39b30SMarc-André Lureau qmp_assert_no_error(ret); 46162c39b30SMarc-André Lureau id = qdict_get_int(ret, "return"); 462cb3e7f08SMarc-André Lureau qobject_unref(ret); 46362c39b30SMarc-André Lureau 46462c39b30SMarc-André Lureau /* read */ 465015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 466015715f5SMarkus Armbruster "{'execute': 'guest-file-read'," 46762c39b30SMarc-André Lureau " 'arguments': { 'handle': %" PRId64 "} }", 46862c39b30SMarc-André Lureau id); 46962c39b30SMarc-André Lureau val = qdict_get_qdict(ret, "return"); 47062c39b30SMarc-André Lureau count = qdict_get_int(val, "count"); 47162c39b30SMarc-André Lureau eof = qdict_get_bool(val, "eof"); 47262c39b30SMarc-André Lureau b64 = qdict_get_str(val, "buf-b64"); 47362c39b30SMarc-André Lureau g_assert_cmpint(count, ==, sizeof(helloworld)); 47462c39b30SMarc-André Lureau g_assert(eof); 47562c39b30SMarc-André Lureau g_assert_cmpstr(b64, ==, enc); 47662c39b30SMarc-André Lureau 477cb3e7f08SMarc-André Lureau qobject_unref(ret); 47862c39b30SMarc-André Lureau g_free(enc); 47962c39b30SMarc-André Lureau 48062c39b30SMarc-André Lureau /* read eof */ 481015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 482015715f5SMarkus Armbruster "{'execute': 'guest-file-read'," 48362c39b30SMarc-André Lureau " 'arguments': { 'handle': %" PRId64 "} }", 48462c39b30SMarc-André Lureau id); 48562c39b30SMarc-André Lureau val = qdict_get_qdict(ret, "return"); 48662c39b30SMarc-André Lureau count = qdict_get_int(val, "count"); 48762c39b30SMarc-André Lureau eof = qdict_get_bool(val, "eof"); 48862c39b30SMarc-André Lureau b64 = qdict_get_str(val, "buf-b64"); 48962c39b30SMarc-André Lureau g_assert_cmpint(count, ==, 0); 49062c39b30SMarc-André Lureau g_assert(eof); 49162c39b30SMarc-André Lureau g_assert_cmpstr(b64, ==, ""); 492cb3e7f08SMarc-André Lureau qobject_unref(ret); 49362c39b30SMarc-André Lureau 49462c39b30SMarc-André Lureau /* seek */ 495015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 496015715f5SMarkus Armbruster "{'execute': 'guest-file-seek'," 49762c39b30SMarc-André Lureau " 'arguments': { 'handle': %" PRId64 ", " 498015715f5SMarkus Armbruster " 'offset': %d, 'whence': %s } }", 4990b4b4938SEric Blake id, 6, "set"); 50062c39b30SMarc-André Lureau qmp_assert_no_error(ret); 50162c39b30SMarc-André Lureau val = qdict_get_qdict(ret, "return"); 50262c39b30SMarc-André Lureau count = qdict_get_int(val, "position"); 50362c39b30SMarc-André Lureau eof = qdict_get_bool(val, "eof"); 50462c39b30SMarc-André Lureau g_assert_cmpint(count, ==, 6); 50562c39b30SMarc-André Lureau g_assert(!eof); 506cb3e7f08SMarc-André Lureau qobject_unref(ret); 50762c39b30SMarc-André Lureau 50862c39b30SMarc-André Lureau /* partial read */ 509015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 510015715f5SMarkus Armbruster "{'execute': 'guest-file-read'," 51162c39b30SMarc-André Lureau " 'arguments': { 'handle': %" PRId64 "} }", 51262c39b30SMarc-André Lureau id); 51362c39b30SMarc-André Lureau val = qdict_get_qdict(ret, "return"); 51462c39b30SMarc-André Lureau count = qdict_get_int(val, "count"); 51562c39b30SMarc-André Lureau eof = qdict_get_bool(val, "eof"); 51662c39b30SMarc-André Lureau b64 = qdict_get_str(val, "buf-b64"); 51762c39b30SMarc-André Lureau g_assert_cmpint(count, ==, sizeof(helloworld) - 6); 51862c39b30SMarc-André Lureau g_assert(eof); 51962c39b30SMarc-André Lureau dec = g_base64_decode(b64, &count); 52062c39b30SMarc-André Lureau g_assert_cmpint(count, ==, sizeof(helloworld) - 6); 52162c39b30SMarc-André Lureau g_assert_cmpmem(dec, count, helloworld + 6, sizeof(helloworld) - 6); 52262c39b30SMarc-André Lureau g_free(dec); 52362c39b30SMarc-André Lureau 524cb3e7f08SMarc-André Lureau qobject_unref(ret); 52562c39b30SMarc-André Lureau 52662c39b30SMarc-André Lureau /* close */ 527015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 528015715f5SMarkus Armbruster "{'execute': 'guest-file-close'," 52962c39b30SMarc-André Lureau " 'arguments': {'handle': %" PRId64 "} }", 53062c39b30SMarc-André Lureau id); 531cb3e7f08SMarc-André Lureau qobject_unref(ret); 53262c39b30SMarc-André Lureau } 53362c39b30SMarc-André Lureau 5344eaab85cSMarc-André Lureau static void test_qga_file_write_read(gconstpointer fix) 5354eaab85cSMarc-André Lureau { 5364eaab85cSMarc-André Lureau const TestFixture *fixture = fix; 5374eaab85cSMarc-André Lureau const unsigned char helloworld[] = "Hello World!\n"; 5384eaab85cSMarc-André Lureau const char *b64; 539015715f5SMarkus Armbruster gchar *enc; 5404eaab85cSMarc-André Lureau QDict *ret, *val; 5414eaab85cSMarc-André Lureau int64_t id, eof; 5424eaab85cSMarc-André Lureau gsize count; 5434eaab85cSMarc-André Lureau 5444eaab85cSMarc-André Lureau /* open */ 5454eaab85cSMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open'," 5464eaab85cSMarc-André Lureau " 'arguments': { 'path': 'foo', 'mode': 'w+' } }"); 5474eaab85cSMarc-André Lureau g_assert_nonnull(ret); 5484eaab85cSMarc-André Lureau qmp_assert_no_error(ret); 5494eaab85cSMarc-André Lureau id = qdict_get_int(ret, "return"); 550cb3e7f08SMarc-André Lureau qobject_unref(ret); 5514eaab85cSMarc-André Lureau 5524eaab85cSMarc-André Lureau enc = g_base64_encode(helloworld, sizeof(helloworld)); 5534eaab85cSMarc-André Lureau /* write */ 554015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 555015715f5SMarkus Armbruster "{'execute': 'guest-file-write'," 5564eaab85cSMarc-André Lureau " 'arguments': { 'handle': %" PRId64 "," 557015715f5SMarkus Armbruster " 'buf-b64': %s } }", id, enc); 5584eaab85cSMarc-André Lureau g_assert_nonnull(ret); 5594eaab85cSMarc-André Lureau qmp_assert_no_error(ret); 5604eaab85cSMarc-André Lureau 5614eaab85cSMarc-André Lureau val = qdict_get_qdict(ret, "return"); 5624eaab85cSMarc-André Lureau count = qdict_get_int(val, "count"); 5634eaab85cSMarc-André Lureau eof = qdict_get_bool(val, "eof"); 5644eaab85cSMarc-André Lureau g_assert_cmpint(count, ==, sizeof(helloworld)); 5654eaab85cSMarc-André Lureau g_assert_cmpint(eof, ==, 0); 566cb3e7f08SMarc-André Lureau qobject_unref(ret); 5674eaab85cSMarc-André Lureau 5684eaab85cSMarc-André Lureau /* read (check implicit flush) */ 569015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 570015715f5SMarkus Armbruster "{'execute': 'guest-file-read'," 5714eaab85cSMarc-André Lureau " 'arguments': { 'handle': %" PRId64 "} }", 5724eaab85cSMarc-André Lureau id); 5734eaab85cSMarc-André Lureau val = qdict_get_qdict(ret, "return"); 5744eaab85cSMarc-André Lureau count = qdict_get_int(val, "count"); 5754eaab85cSMarc-André Lureau eof = qdict_get_bool(val, "eof"); 5764eaab85cSMarc-André Lureau b64 = qdict_get_str(val, "buf-b64"); 5774eaab85cSMarc-André Lureau g_assert_cmpint(count, ==, 0); 5784eaab85cSMarc-André Lureau g_assert(eof); 5794eaab85cSMarc-André Lureau g_assert_cmpstr(b64, ==, ""); 580cb3e7f08SMarc-André Lureau qobject_unref(ret); 5814eaab85cSMarc-André Lureau 5824eaab85cSMarc-André Lureau /* seek to 0 */ 583015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 584015715f5SMarkus Armbruster "{'execute': 'guest-file-seek'," 5854eaab85cSMarc-André Lureau " 'arguments': { 'handle': %" PRId64 ", " 586015715f5SMarkus Armbruster " 'offset': %d, 'whence': %s } }", 5870b4b4938SEric Blake id, 0, "set"); 5884eaab85cSMarc-André Lureau qmp_assert_no_error(ret); 5894eaab85cSMarc-André Lureau val = qdict_get_qdict(ret, "return"); 5904eaab85cSMarc-André Lureau count = qdict_get_int(val, "position"); 5914eaab85cSMarc-André Lureau eof = qdict_get_bool(val, "eof"); 5924eaab85cSMarc-André Lureau g_assert_cmpint(count, ==, 0); 5934eaab85cSMarc-André Lureau g_assert(!eof); 594cb3e7f08SMarc-André Lureau qobject_unref(ret); 5954eaab85cSMarc-André Lureau 5964eaab85cSMarc-André Lureau /* read */ 597015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 598015715f5SMarkus Armbruster "{'execute': 'guest-file-read'," 5994eaab85cSMarc-André Lureau " 'arguments': { 'handle': %" PRId64 "} }", 6004eaab85cSMarc-André Lureau id); 6014eaab85cSMarc-André Lureau val = qdict_get_qdict(ret, "return"); 6024eaab85cSMarc-André Lureau count = qdict_get_int(val, "count"); 6034eaab85cSMarc-André Lureau eof = qdict_get_bool(val, "eof"); 6044eaab85cSMarc-André Lureau b64 = qdict_get_str(val, "buf-b64"); 6054eaab85cSMarc-André Lureau g_assert_cmpint(count, ==, sizeof(helloworld)); 6064eaab85cSMarc-André Lureau g_assert(eof); 6074eaab85cSMarc-André Lureau g_assert_cmpstr(b64, ==, enc); 608cb3e7f08SMarc-André Lureau qobject_unref(ret); 6094eaab85cSMarc-André Lureau g_free(enc); 6104eaab85cSMarc-André Lureau 6114eaab85cSMarc-André Lureau /* close */ 612015715f5SMarkus Armbruster ret = qmp_fd(fixture->fd, 613015715f5SMarkus Armbruster "{'execute': 'guest-file-close'," 6144eaab85cSMarc-André Lureau " 'arguments': {'handle': %" PRId64 "} }", 6154eaab85cSMarc-André Lureau id); 616cb3e7f08SMarc-André Lureau qobject_unref(ret); 6174eaab85cSMarc-André Lureau } 6184eaab85cSMarc-André Lureau 61962c39b30SMarc-André Lureau static void test_qga_get_time(gconstpointer fix) 62062c39b30SMarc-André Lureau { 62162c39b30SMarc-André Lureau const TestFixture *fixture = fix; 622bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 62362c39b30SMarc-André Lureau int64_t time; 62462c39b30SMarc-André Lureau 62562c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}"); 62662c39b30SMarc-André Lureau g_assert_nonnull(ret); 62762c39b30SMarc-André Lureau qmp_assert_no_error(ret); 62862c39b30SMarc-André Lureau 62962c39b30SMarc-André Lureau time = qdict_get_int(ret, "return"); 63062c39b30SMarc-André Lureau g_assert_cmpint(time, >, 0); 63162c39b30SMarc-André Lureau } 63262c39b30SMarc-André Lureau 633ebf70554SThomas Huth static void test_qga_blockedrpcs(gconstpointer data) 63462c39b30SMarc-André Lureau { 63562c39b30SMarc-André Lureau TestFixture fix; 63662c39b30SMarc-André Lureau QDict *ret, *error; 63762c39b30SMarc-André Lureau const gchar *class, *desc; 63862c39b30SMarc-André Lureau 639c28afa76STomáš Golembiovský fixture_setup(&fix, "-b guest-ping,guest-get-time", NULL); 64062c39b30SMarc-André Lureau 641ebf70554SThomas Huth /* check blocked RPCs */ 64262c39b30SMarc-André Lureau ret = qmp_fd(fix.fd, "{'execute': 'guest-ping'}"); 64362c39b30SMarc-André Lureau g_assert_nonnull(ret); 64462c39b30SMarc-André Lureau error = qdict_get_qdict(ret, "error"); 64562c39b30SMarc-André Lureau class = qdict_get_try_str(error, "class"); 64662c39b30SMarc-André Lureau desc = qdict_get_try_str(error, "desc"); 6472546be1cSMichal Privoznik g_assert_cmpstr(class, ==, "CommandNotFound"); 64862c39b30SMarc-André Lureau g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled")); 649cb3e7f08SMarc-André Lureau qobject_unref(ret); 65062c39b30SMarc-André Lureau 65162c39b30SMarc-André Lureau ret = qmp_fd(fix.fd, "{'execute': 'guest-get-time'}"); 65262c39b30SMarc-André Lureau g_assert_nonnull(ret); 65362c39b30SMarc-André Lureau error = qdict_get_qdict(ret, "error"); 65462c39b30SMarc-André Lureau class = qdict_get_try_str(error, "class"); 65562c39b30SMarc-André Lureau desc = qdict_get_try_str(error, "desc"); 6562546be1cSMichal Privoznik g_assert_cmpstr(class, ==, "CommandNotFound"); 65762c39b30SMarc-André Lureau g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled")); 658cb3e7f08SMarc-André Lureau qobject_unref(ret); 65962c39b30SMarc-André Lureau 66062c39b30SMarc-André Lureau /* check something work */ 66162c39b30SMarc-André Lureau ret = qmp_fd(fix.fd, "{'execute': 'guest-get-fsinfo'}"); 66262c39b30SMarc-André Lureau qmp_assert_no_error(ret); 663cb3e7f08SMarc-André Lureau qobject_unref(ret); 66462c39b30SMarc-André Lureau 66562c39b30SMarc-André Lureau fixture_tear_down(&fix, NULL); 66662c39b30SMarc-André Lureau } 66762c39b30SMarc-André Lureau 66862c39b30SMarc-André Lureau static void test_qga_config(gconstpointer data) 66962c39b30SMarc-André Lureau { 67062c39b30SMarc-André Lureau GError *error = NULL; 671bb6960a1SMarc-André Lureau g_autofree char *out = NULL; 672bb6960a1SMarc-André Lureau g_autofree char *err = NULL; 673bb6960a1SMarc-André Lureau g_autofree char *cwd = NULL; 674bb6960a1SMarc-André Lureau g_autofree char *cmd = NULL; 675bb6960a1SMarc-André Lureau g_auto(GStrv) argv = NULL; 676bb6960a1SMarc-André Lureau g_auto(GStrv) strv = NULL; 677bb6960a1SMarc-André Lureau g_autoptr(GKeyFile) kf = NULL; 678bb6960a1SMarc-André Lureau char *str; 67962c39b30SMarc-André Lureau char *env[2]; 6801741b945SMarc-André Lureau int status; 68162c39b30SMarc-André Lureau gsize n; 68262c39b30SMarc-André Lureau 68362c39b30SMarc-André Lureau cwd = g_get_current_dir(); 684f15bff25SPaolo Bonzini cmd = g_strdup_printf("%s%cqga%cqemu-ga -D", 685f15bff25SPaolo Bonzini cwd, G_DIR_SEPARATOR, G_DIR_SEPARATOR); 68662c39b30SMarc-André Lureau g_shell_parse_argv(cmd, NULL, &argv, &error); 68762c39b30SMarc-André Lureau g_assert_no_error(error); 68862c39b30SMarc-André Lureau 6891741b945SMarc-André Lureau env[0] = g_strdup_printf("QGA_CONF=tests%cdata%ctest-qga-config", 6901741b945SMarc-André Lureau G_DIR_SEPARATOR, G_DIR_SEPARATOR); 69162c39b30SMarc-André Lureau env[1] = NULL; 69262c39b30SMarc-André Lureau g_spawn_sync(NULL, argv, env, 0, 69362c39b30SMarc-André Lureau NULL, NULL, &out, &err, &status, &error); 6941e271338SMarc-André Lureau 69562c39b30SMarc-André Lureau g_assert_no_error(error); 69662c39b30SMarc-André Lureau g_assert_cmpstr(err, ==, ""); 69762c39b30SMarc-André Lureau g_assert_cmpint(status, ==, 0); 69862c39b30SMarc-André Lureau 69962c39b30SMarc-André Lureau kf = g_key_file_new(); 70062c39b30SMarc-André Lureau g_key_file_load_from_data(kf, out, -1, G_KEY_FILE_NONE, &error); 70162c39b30SMarc-André Lureau g_assert_no_error(error); 70262c39b30SMarc-André Lureau 70362c39b30SMarc-André Lureau str = g_key_file_get_start_group(kf); 70462c39b30SMarc-André Lureau g_assert_cmpstr(str, ==, "general"); 70562c39b30SMarc-André Lureau g_free(str); 70662c39b30SMarc-André Lureau 70762c39b30SMarc-André Lureau g_assert_false(g_key_file_get_boolean(kf, "general", "daemon", &error)); 70862c39b30SMarc-André Lureau g_assert_no_error(error); 70962c39b30SMarc-André Lureau 71062c39b30SMarc-André Lureau str = g_key_file_get_string(kf, "general", "method", &error); 71162c39b30SMarc-André Lureau g_assert_no_error(error); 71262c39b30SMarc-André Lureau g_assert_cmpstr(str, ==, "virtio-serial"); 71362c39b30SMarc-André Lureau g_free(str); 71462c39b30SMarc-André Lureau 71562c39b30SMarc-André Lureau str = g_key_file_get_string(kf, "general", "path", &error); 71662c39b30SMarc-André Lureau g_assert_no_error(error); 71762c39b30SMarc-André Lureau g_assert_cmpstr(str, ==, "/path/to/org.qemu.guest_agent.0"); 71862c39b30SMarc-André Lureau g_free(str); 71962c39b30SMarc-André Lureau 72062c39b30SMarc-André Lureau str = g_key_file_get_string(kf, "general", "pidfile", &error); 72162c39b30SMarc-André Lureau g_assert_no_error(error); 72262c39b30SMarc-André Lureau g_assert_cmpstr(str, ==, "/var/foo/qemu-ga.pid"); 72362c39b30SMarc-André Lureau g_free(str); 72462c39b30SMarc-André Lureau 72562c39b30SMarc-André Lureau str = g_key_file_get_string(kf, "general", "statedir", &error); 72662c39b30SMarc-André Lureau g_assert_no_error(error); 72762c39b30SMarc-André Lureau g_assert_cmpstr(str, ==, "/var/state"); 72862c39b30SMarc-André Lureau g_free(str); 72962c39b30SMarc-André Lureau 73062c39b30SMarc-André Lureau g_assert_true(g_key_file_get_boolean(kf, "general", "verbose", &error)); 73162c39b30SMarc-André Lureau g_assert_no_error(error); 73262c39b30SMarc-André Lureau 733582a098eSThomas Huth strv = g_key_file_get_string_list(kf, "general", "block-rpcs", &n, &error); 73462c39b30SMarc-André Lureau g_assert_cmpint(n, ==, 2); 73562c39b30SMarc-André Lureau g_assert_true(g_strv_contains((const char * const *)strv, 73662c39b30SMarc-André Lureau "guest-ping")); 73762c39b30SMarc-André Lureau g_assert_true(g_strv_contains((const char * const *)strv, 73862c39b30SMarc-André Lureau "guest-get-time")); 73962c39b30SMarc-André Lureau g_assert_no_error(error); 74062c39b30SMarc-André Lureau 74162c39b30SMarc-André Lureau g_free(env[0]); 74262c39b30SMarc-André Lureau } 74362c39b30SMarc-André Lureau 74462c39b30SMarc-André Lureau static void test_qga_fsfreeze_status(gconstpointer fix) 74562c39b30SMarc-André Lureau { 74662c39b30SMarc-André Lureau const TestFixture *fixture = fix; 747bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 74862c39b30SMarc-André Lureau const gchar *status; 74962c39b30SMarc-André Lureau 75062c39b30SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}"); 75162c39b30SMarc-André Lureau g_assert_nonnull(ret); 75262c39b30SMarc-André Lureau qmp_assert_no_error(ret); 75362c39b30SMarc-André Lureau 75462c39b30SMarc-André Lureau status = qdict_get_try_str(ret, "return"); 75562c39b30SMarc-André Lureau g_assert_cmpstr(status, ==, "thawed"); 75662c39b30SMarc-André Lureau } 75762c39b30SMarc-André Lureau 758*c7d74f27SDaniel Xu static QDict *wait_for_guest_exec_completion(int fd, int64_t pid) 7593dab9fa1SMarc-André Lureau { 760*c7d74f27SDaniel Xu QDict *ret = NULL; 761*c7d74f27SDaniel Xu int64_t now; 7623dab9fa1SMarc-André Lureau bool exited; 763*c7d74f27SDaniel Xu QDict *val; 7643dab9fa1SMarc-André Lureau 7653dab9fa1SMarc-André Lureau now = g_get_monotonic_time(); 7661792d7d0SEric Blake do { 767*c7d74f27SDaniel Xu ret = qmp_fd(fd, 768015715f5SMarkus Armbruster "{'execute': 'guest-exec-status'," 769015715f5SMarkus Armbruster " 'arguments': { 'pid': %" PRId64 " } }", pid); 7703dab9fa1SMarc-André Lureau g_assert_nonnull(ret); 7713dab9fa1SMarc-André Lureau val = qdict_get_qdict(ret, "return"); 7723dab9fa1SMarc-André Lureau exited = qdict_get_bool(val, "exited"); 7733dab9fa1SMarc-André Lureau if (!exited) { 774cb3e7f08SMarc-André Lureau qobject_unref(ret); 7753dab9fa1SMarc-André Lureau } 7763dab9fa1SMarc-André Lureau } while (!exited && 7773dab9fa1SMarc-André Lureau g_get_monotonic_time() < now + 5 * G_TIME_SPAN_SECOND); 7783dab9fa1SMarc-André Lureau g_assert(exited); 7793dab9fa1SMarc-André Lureau 780*c7d74f27SDaniel Xu return ret; 781*c7d74f27SDaniel Xu } 782*c7d74f27SDaniel Xu 783*c7d74f27SDaniel Xu static void test_qga_guest_exec(gconstpointer fix) 784*c7d74f27SDaniel Xu { 785*c7d74f27SDaniel Xu const TestFixture *fixture = fix; 786*c7d74f27SDaniel Xu g_autoptr(QDict) ret = NULL; 787*c7d74f27SDaniel Xu QDict *val; 788*c7d74f27SDaniel Xu const gchar *out; 789*c7d74f27SDaniel Xu g_autofree guchar *decoded = NULL; 790*c7d74f27SDaniel Xu int64_t pid, exitcode; 791*c7d74f27SDaniel Xu gsize len; 792*c7d74f27SDaniel Xu 793*c7d74f27SDaniel Xu /* exec 'echo foo bar' */ 794*c7d74f27SDaniel Xu ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" 795*c7d74f27SDaniel Xu " 'path': '/bin/echo', 'arg': [ '-n', '\" test_str \"' ]," 796*c7d74f27SDaniel Xu " 'capture-output': true } }"); 797*c7d74f27SDaniel Xu g_assert_nonnull(ret); 798*c7d74f27SDaniel Xu qmp_assert_no_error(ret); 799*c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return"); 800*c7d74f27SDaniel Xu pid = qdict_get_int(val, "pid"); 801*c7d74f27SDaniel Xu g_assert_cmpint(pid, >, 0); 802*c7d74f27SDaniel Xu qobject_unref(ret); 803*c7d74f27SDaniel Xu 804*c7d74f27SDaniel Xu ret = wait_for_guest_exec_completion(fixture->fd, pid); 805*c7d74f27SDaniel Xu 8063dab9fa1SMarc-André Lureau /* check stdout */ 807*c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return"); 8083dab9fa1SMarc-André Lureau exitcode = qdict_get_int(val, "exitcode"); 8093dab9fa1SMarc-André Lureau g_assert_cmpint(exitcode, ==, 0); 8103dab9fa1SMarc-André Lureau out = qdict_get_str(val, "out-data"); 8113dab9fa1SMarc-André Lureau decoded = g_base64_decode(out, &len); 8123dab9fa1SMarc-André Lureau g_assert_cmpint(len, ==, 12); 8133dab9fa1SMarc-André Lureau g_assert_cmpstr((char *)decoded, ==, "\" test_str \""); 8143dab9fa1SMarc-André Lureau } 8153dab9fa1SMarc-André Lureau 816*c7d74f27SDaniel Xu #if defined(G_OS_WIN32) 817*c7d74f27SDaniel Xu static void test_qga_guest_exec_separated(gconstpointer fix) 818*c7d74f27SDaniel Xu { 819*c7d74f27SDaniel Xu } 820*c7d74f27SDaniel Xu static void test_qga_guest_exec_merged(gconstpointer fix) 821*c7d74f27SDaniel Xu { 822*c7d74f27SDaniel Xu const TestFixture *fixture = fix; 823*c7d74f27SDaniel Xu g_autoptr(QDict) ret = NULL; 824*c7d74f27SDaniel Xu QDict *val; 825*c7d74f27SDaniel Xu const gchar *class, *desc; 826*c7d74f27SDaniel Xu g_autofree guchar *decoded = NULL; 827*c7d74f27SDaniel Xu 828*c7d74f27SDaniel Xu /* exec 'echo foo bar' */ 829*c7d74f27SDaniel Xu ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" 830*c7d74f27SDaniel Xu " 'path': 'echo'," 831*c7d74f27SDaniel Xu " 'arg': [ 'execution never reaches here' ]," 832*c7d74f27SDaniel Xu " 'capture-output': 'merged' } }"); 833*c7d74f27SDaniel Xu 834*c7d74f27SDaniel Xu g_assert_nonnull(ret); 835*c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "error"); 836*c7d74f27SDaniel Xu g_assert_nonnull(val); 837*c7d74f27SDaniel Xu class = qdict_get_str(val, "class"); 838*c7d74f27SDaniel Xu desc = qdict_get_str(val, "desc"); 839*c7d74f27SDaniel Xu g_assert_cmpstr(class, ==, "GenericError"); 840*c7d74f27SDaniel Xu g_assert_cmpint(strlen(desc), >, 0); 841*c7d74f27SDaniel Xu } 842*c7d74f27SDaniel Xu #else 843*c7d74f27SDaniel Xu static void test_qga_guest_exec_separated(gconstpointer fix) 844*c7d74f27SDaniel Xu { 845*c7d74f27SDaniel Xu const TestFixture *fixture = fix; 846*c7d74f27SDaniel Xu g_autoptr(QDict) ret = NULL; 847*c7d74f27SDaniel Xu QDict *val; 848*c7d74f27SDaniel Xu const gchar *out, *err; 849*c7d74f27SDaniel Xu g_autofree guchar *out_decoded = NULL; 850*c7d74f27SDaniel Xu g_autofree guchar *err_decoded = NULL; 851*c7d74f27SDaniel Xu int64_t pid, exitcode; 852*c7d74f27SDaniel Xu gsize len; 853*c7d74f27SDaniel Xu 854*c7d74f27SDaniel Xu /* exec 'echo foo bar' */ 855*c7d74f27SDaniel Xu ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" 856*c7d74f27SDaniel Xu " 'path': '/bin/bash'," 857*c7d74f27SDaniel Xu " 'arg': [ '-c', 'for i in $(seq 4); do if (( $i %% 2 )); then echo stdout; else echo stderr 1>&2; fi; done;' ]," 858*c7d74f27SDaniel Xu " 'capture-output': 'separated' } }"); 859*c7d74f27SDaniel Xu g_assert_nonnull(ret); 860*c7d74f27SDaniel Xu qmp_assert_no_error(ret); 861*c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return"); 862*c7d74f27SDaniel Xu pid = qdict_get_int(val, "pid"); 863*c7d74f27SDaniel Xu g_assert_cmpint(pid, >, 0); 864*c7d74f27SDaniel Xu qobject_unref(ret); 865*c7d74f27SDaniel Xu 866*c7d74f27SDaniel Xu ret = wait_for_guest_exec_completion(fixture->fd, pid); 867*c7d74f27SDaniel Xu 868*c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return"); 869*c7d74f27SDaniel Xu exitcode = qdict_get_int(val, "exitcode"); 870*c7d74f27SDaniel Xu g_assert_cmpint(exitcode, ==, 0); 871*c7d74f27SDaniel Xu 872*c7d74f27SDaniel Xu /* check stdout */ 873*c7d74f27SDaniel Xu out = qdict_get_str(val, "out-data"); 874*c7d74f27SDaniel Xu out_decoded = g_base64_decode(out, &len); 875*c7d74f27SDaniel Xu g_assert_cmpint(len, ==, 14); 876*c7d74f27SDaniel Xu g_assert_cmpstr((char *)out_decoded, ==, "stdout\nstdout\n"); 877*c7d74f27SDaniel Xu 878*c7d74f27SDaniel Xu /* check stderr */ 879*c7d74f27SDaniel Xu err = qdict_get_try_str(val, "err-data"); 880*c7d74f27SDaniel Xu err_decoded = g_base64_decode(err, &len); 881*c7d74f27SDaniel Xu g_assert_cmpint(len, ==, 14); 882*c7d74f27SDaniel Xu g_assert_cmpstr((char *)err_decoded, ==, "stderr\nstderr\n"); 883*c7d74f27SDaniel Xu } 884*c7d74f27SDaniel Xu 885*c7d74f27SDaniel Xu static void test_qga_guest_exec_merged(gconstpointer fix) 886*c7d74f27SDaniel Xu { 887*c7d74f27SDaniel Xu const TestFixture *fixture = fix; 888*c7d74f27SDaniel Xu g_autoptr(QDict) ret = NULL; 889*c7d74f27SDaniel Xu QDict *val; 890*c7d74f27SDaniel Xu const gchar *out, *err; 891*c7d74f27SDaniel Xu g_autofree guchar *decoded = NULL; 892*c7d74f27SDaniel Xu int64_t pid, exitcode; 893*c7d74f27SDaniel Xu gsize len; 894*c7d74f27SDaniel Xu 895*c7d74f27SDaniel Xu /* exec 'echo foo bar' */ 896*c7d74f27SDaniel Xu ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" 897*c7d74f27SDaniel Xu " 'path': '/bin/bash'," 898*c7d74f27SDaniel Xu " 'arg': [ '-c', 'for i in $(seq 4); do if (( $i %% 2 )); then echo stdout; else echo stderr 1>&2; fi; done;' ]," 899*c7d74f27SDaniel Xu " 'capture-output': 'merged' } }"); 900*c7d74f27SDaniel Xu g_assert_nonnull(ret); 901*c7d74f27SDaniel Xu qmp_assert_no_error(ret); 902*c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return"); 903*c7d74f27SDaniel Xu pid = qdict_get_int(val, "pid"); 904*c7d74f27SDaniel Xu g_assert_cmpint(pid, >, 0); 905*c7d74f27SDaniel Xu qobject_unref(ret); 906*c7d74f27SDaniel Xu 907*c7d74f27SDaniel Xu ret = wait_for_guest_exec_completion(fixture->fd, pid); 908*c7d74f27SDaniel Xu 909*c7d74f27SDaniel Xu val = qdict_get_qdict(ret, "return"); 910*c7d74f27SDaniel Xu exitcode = qdict_get_int(val, "exitcode"); 911*c7d74f27SDaniel Xu g_assert_cmpint(exitcode, ==, 0); 912*c7d74f27SDaniel Xu 913*c7d74f27SDaniel Xu /* check stdout */ 914*c7d74f27SDaniel Xu out = qdict_get_str(val, "out-data"); 915*c7d74f27SDaniel Xu decoded = g_base64_decode(out, &len); 916*c7d74f27SDaniel Xu g_assert_cmpint(len, ==, 28); 917*c7d74f27SDaniel Xu g_assert_cmpstr((char *)decoded, ==, "stdout\nstderr\nstdout\nstderr\n"); 918*c7d74f27SDaniel Xu 919*c7d74f27SDaniel Xu /* check stderr */ 920*c7d74f27SDaniel Xu err = qdict_get_try_str(val, "err-data"); 921*c7d74f27SDaniel Xu g_assert_null(err); 922*c7d74f27SDaniel Xu } 923*c7d74f27SDaniel Xu #endif 924*c7d74f27SDaniel Xu 9253dab9fa1SMarc-André Lureau static void test_qga_guest_exec_invalid(gconstpointer fix) 9263dab9fa1SMarc-André Lureau { 9273dab9fa1SMarc-André Lureau const TestFixture *fixture = fix; 928bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 929bb6960a1SMarc-André Lureau QDict *error; 9303dab9fa1SMarc-André Lureau const gchar *class, *desc; 9313dab9fa1SMarc-André Lureau 9323dab9fa1SMarc-André Lureau /* invalid command */ 9333dab9fa1SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {" 9343dab9fa1SMarc-André Lureau " 'path': '/bin/invalid-cmd42' } }"); 9353dab9fa1SMarc-André Lureau g_assert_nonnull(ret); 9363dab9fa1SMarc-André Lureau error = qdict_get_qdict(ret, "error"); 9373dab9fa1SMarc-André Lureau g_assert_nonnull(error); 9383dab9fa1SMarc-André Lureau class = qdict_get_str(error, "class"); 9393dab9fa1SMarc-André Lureau desc = qdict_get_str(error, "desc"); 9403dab9fa1SMarc-André Lureau g_assert_cmpstr(class, ==, "GenericError"); 9413dab9fa1SMarc-André Lureau g_assert_cmpint(strlen(desc), >, 0); 942cb3e7f08SMarc-André Lureau qobject_unref(ret); 9433dab9fa1SMarc-André Lureau 9443dab9fa1SMarc-André Lureau /* invalid pid */ 9453dab9fa1SMarc-André Lureau ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec-status'," 9463dab9fa1SMarc-André Lureau " 'arguments': { 'pid': 0 } }"); 9473dab9fa1SMarc-André Lureau g_assert_nonnull(ret); 9483dab9fa1SMarc-André Lureau error = qdict_get_qdict(ret, "error"); 9493dab9fa1SMarc-André Lureau g_assert_nonnull(error); 9503dab9fa1SMarc-André Lureau class = qdict_get_str(error, "class"); 9513dab9fa1SMarc-André Lureau desc = qdict_get_str(error, "desc"); 9523dab9fa1SMarc-André Lureau g_assert_cmpstr(class, ==, "GenericError"); 9533dab9fa1SMarc-André Lureau g_assert_cmpint(strlen(desc), >, 0); 9543dab9fa1SMarc-André Lureau } 9553dab9fa1SMarc-André Lureau 956509b97fdSTomáš Golembiovský static void test_qga_guest_get_host_name(gconstpointer fix) 957509b97fdSTomáš Golembiovský { 958509b97fdSTomáš Golembiovský const TestFixture *fixture = fix; 959bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 960bb6960a1SMarc-André Lureau QDict *val; 961509b97fdSTomáš Golembiovský 962509b97fdSTomáš Golembiovský ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-host-name'}"); 963509b97fdSTomáš Golembiovský g_assert_nonnull(ret); 964509b97fdSTomáš Golembiovský qmp_assert_no_error(ret); 965509b97fdSTomáš Golembiovský 966509b97fdSTomáš Golembiovský val = qdict_get_qdict(ret, "return"); 967509b97fdSTomáš Golembiovský g_assert(qdict_haskey(val, "host-name")); 968509b97fdSTomáš Golembiovský } 969509b97fdSTomáš Golembiovský 970509b97fdSTomáš Golembiovský static void test_qga_guest_get_timezone(gconstpointer fix) 971509b97fdSTomáš Golembiovský { 972509b97fdSTomáš Golembiovský const TestFixture *fixture = fix; 973bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 974bb6960a1SMarc-André Lureau QDict *val; 975509b97fdSTomáš Golembiovský 976509b97fdSTomáš Golembiovský ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-timezone'}"); 977509b97fdSTomáš Golembiovský g_assert_nonnull(ret); 978509b97fdSTomáš Golembiovský qmp_assert_no_error(ret); 979509b97fdSTomáš Golembiovský 980509b97fdSTomáš Golembiovský /* Make sure there's at least offset */ 981509b97fdSTomáš Golembiovský val = qdict_get_qdict(ret, "return"); 982509b97fdSTomáš Golembiovský g_assert(qdict_haskey(val, "offset")); 983509b97fdSTomáš Golembiovský } 984509b97fdSTomáš Golembiovský 985509b97fdSTomáš Golembiovský static void test_qga_guest_get_users(gconstpointer fix) 986509b97fdSTomáš Golembiovský { 987509b97fdSTomáš Golembiovský const TestFixture *fixture = fix; 988bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 989509b97fdSTomáš Golembiovský QList *val; 990509b97fdSTomáš Golembiovský 991509b97fdSTomáš Golembiovský ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-users'}"); 992509b97fdSTomáš Golembiovský g_assert_nonnull(ret); 993509b97fdSTomáš Golembiovský qmp_assert_no_error(ret); 994509b97fdSTomáš Golembiovský 995509b97fdSTomáš Golembiovský /* There is not much to test here */ 996509b97fdSTomáš Golembiovský val = qdict_get_qlist(ret, "return"); 997509b97fdSTomáš Golembiovský g_assert_nonnull(val); 998509b97fdSTomáš Golembiovský } 999509b97fdSTomáš Golembiovský 1000339ca68bSTomáš Golembiovský static void test_qga_guest_get_osinfo(gconstpointer data) 1001339ca68bSTomáš Golembiovský { 1002339ca68bSTomáš Golembiovský TestFixture fixture; 1003339ca68bSTomáš Golembiovský const gchar *str; 1004bb6960a1SMarc-André Lureau g_autoptr(QDict) ret = NULL; 1005a85d0926SMarc-André Lureau char *env[2]; 1006a85d0926SMarc-André Lureau QDict *val; 1007339ca68bSTomáš Golembiovský 1008339ca68bSTomáš Golembiovský env[0] = g_strdup_printf( 1009a85d0926SMarc-André Lureau "QGA_OS_RELEASE=%s%c..%cdata%ctest-qga-os-release", 1010a85d0926SMarc-André Lureau g_test_get_dir(G_TEST_DIST), G_DIR_SEPARATOR, G_DIR_SEPARATOR, G_DIR_SEPARATOR); 1011339ca68bSTomáš Golembiovský env[1] = NULL; 1012339ca68bSTomáš Golembiovský fixture_setup(&fixture, NULL, env); 1013339ca68bSTomáš Golembiovský 1014339ca68bSTomáš Golembiovský ret = qmp_fd(fixture.fd, "{'execute': 'guest-get-osinfo'}"); 1015339ca68bSTomáš Golembiovský g_assert_nonnull(ret); 1016339ca68bSTomáš Golembiovský qmp_assert_no_error(ret); 1017339ca68bSTomáš Golembiovský 1018339ca68bSTomáš Golembiovský val = qdict_get_qdict(ret, "return"); 1019339ca68bSTomáš Golembiovský 1020339ca68bSTomáš Golembiovský str = qdict_get_try_str(val, "id"); 1021339ca68bSTomáš Golembiovský g_assert_nonnull(str); 1022339ca68bSTomáš Golembiovský g_assert_cmpstr(str, ==, "qemu-ga-test"); 1023339ca68bSTomáš Golembiovský 1024339ca68bSTomáš Golembiovský str = qdict_get_try_str(val, "name"); 1025339ca68bSTomáš Golembiovský g_assert_nonnull(str); 1026339ca68bSTomáš Golembiovský g_assert_cmpstr(str, ==, "QEMU-GA"); 1027339ca68bSTomáš Golembiovský 1028339ca68bSTomáš Golembiovský str = qdict_get_try_str(val, "pretty-name"); 1029339ca68bSTomáš Golembiovský g_assert_nonnull(str); 1030339ca68bSTomáš Golembiovský g_assert_cmpstr(str, ==, "QEMU Guest Agent test"); 1031339ca68bSTomáš Golembiovský 1032339ca68bSTomáš Golembiovský str = qdict_get_try_str(val, "version"); 1033339ca68bSTomáš Golembiovský g_assert_nonnull(str); 1034339ca68bSTomáš Golembiovský g_assert_cmpstr(str, ==, "Test 1"); 1035339ca68bSTomáš Golembiovský 1036339ca68bSTomáš Golembiovský str = qdict_get_try_str(val, "version-id"); 1037339ca68bSTomáš Golembiovský g_assert_nonnull(str); 1038339ca68bSTomáš Golembiovský g_assert_cmpstr(str, ==, "1"); 1039339ca68bSTomáš Golembiovský 1040339ca68bSTomáš Golembiovský str = qdict_get_try_str(val, "variant"); 1041339ca68bSTomáš Golembiovský g_assert_nonnull(str); 1042339ca68bSTomáš Golembiovský g_assert_cmpstr(str, ==, "Unit test \"'$`\\ and \\\\ etc."); 1043339ca68bSTomáš Golembiovský 1044339ca68bSTomáš Golembiovský str = qdict_get_try_str(val, "variant-id"); 1045339ca68bSTomáš Golembiovský g_assert_nonnull(str); 1046339ca68bSTomáš Golembiovský g_assert_cmpstr(str, ==, "unit-test"); 1047339ca68bSTomáš Golembiovský 1048339ca68bSTomáš Golembiovský g_free(env[0]); 1049339ca68bSTomáš Golembiovský fixture_tear_down(&fixture, NULL); 1050339ca68bSTomáš Golembiovský } 1051339ca68bSTomáš Golembiovský 105262c39b30SMarc-André Lureau int main(int argc, char **argv) 105362c39b30SMarc-André Lureau { 105462c39b30SMarc-André Lureau TestFixture fix; 105562c39b30SMarc-André Lureau int ret; 105662c39b30SMarc-André Lureau 1057a7bd942cSMarc-André Lureau #ifdef QEMU_SANITIZE_THREAD 1058a7bd942cSMarc-André Lureau { 1059a7bd942cSMarc-André Lureau g_test_skip("tsan enabled, https://github.com/google/sanitizers/issues/1116"); 1060a7bd942cSMarc-André Lureau return 0; 1061a7bd942cSMarc-André Lureau } 1062a7bd942cSMarc-André Lureau #endif 1063a7bd942cSMarc-André Lureau 106462c39b30SMarc-André Lureau setlocale (LC_ALL, ""); 106562c39b30SMarc-André Lureau g_test_init(&argc, &argv, NULL); 1066c28afa76STomáš Golembiovský fixture_setup(&fix, NULL, NULL); 106762c39b30SMarc-André Lureau 106862c39b30SMarc-André Lureau g_test_add_data_func("/qga/sync-delimited", &fix, test_qga_sync_delimited); 106962c39b30SMarc-André Lureau g_test_add_data_func("/qga/sync", &fix, test_qga_sync); 107062c39b30SMarc-André Lureau g_test_add_data_func("/qga/ping", &fix, test_qga_ping); 107162c39b30SMarc-André Lureau g_test_add_data_func("/qga/info", &fix, test_qga_info); 107262c39b30SMarc-André Lureau g_test_add_data_func("/qga/network-get-interfaces", &fix, 107362c39b30SMarc-André Lureau test_qga_network_get_interfaces); 1074ec72c0e2SBruce Rogers if (!access("/sys/devices/system/cpu/cpu0", F_OK)) { 107562c39b30SMarc-André Lureau g_test_add_data_func("/qga/get-vcpus", &fix, test_qga_get_vcpus); 1076ec72c0e2SBruce Rogers } 107762c39b30SMarc-André Lureau g_test_add_data_func("/qga/get-fsinfo", &fix, test_qga_get_fsinfo); 107862c39b30SMarc-André Lureau g_test_add_data_func("/qga/get-memory-block-info", &fix, 107962c39b30SMarc-André Lureau test_qga_get_memory_block_info); 108062c39b30SMarc-André Lureau g_test_add_data_func("/qga/get-memory-blocks", &fix, 108162c39b30SMarc-André Lureau test_qga_get_memory_blocks); 108262c39b30SMarc-André Lureau g_test_add_data_func("/qga/file-ops", &fix, test_qga_file_ops); 10834eaab85cSMarc-André Lureau g_test_add_data_func("/qga/file-write-read", &fix, test_qga_file_write_read); 108462c39b30SMarc-André Lureau g_test_add_data_func("/qga/get-time", &fix, test_qga_get_time); 10854eaca8deSMarc-André Lureau g_test_add_data_func("/qga/id", &fix, test_qga_id); 1086d4d7ed73SMarkus Armbruster g_test_add_data_func("/qga/invalid-oob", &fix, test_qga_invalid_oob); 108762c39b30SMarc-André Lureau g_test_add_data_func("/qga/invalid-cmd", &fix, test_qga_invalid_cmd); 10884bdadd86SMarc-André Lureau g_test_add_data_func("/qga/invalid-args", &fix, test_qga_invalid_args); 108962c39b30SMarc-André Lureau g_test_add_data_func("/qga/fsfreeze-status", &fix, 109062c39b30SMarc-André Lureau test_qga_fsfreeze_status); 109162c39b30SMarc-André Lureau 1092ebf70554SThomas Huth g_test_add_data_func("/qga/blockedrpcs", NULL, test_qga_blockedrpcs); 109362c39b30SMarc-André Lureau g_test_add_data_func("/qga/config", NULL, test_qga_config); 10943dab9fa1SMarc-André Lureau g_test_add_data_func("/qga/guest-exec", &fix, test_qga_guest_exec); 1095*c7d74f27SDaniel Xu g_test_add_data_func("/qga/guest-exec-separated", &fix, 1096*c7d74f27SDaniel Xu test_qga_guest_exec_separated); 1097*c7d74f27SDaniel Xu g_test_add_data_func("/qga/guest-exec-merged", &fix, 1098*c7d74f27SDaniel Xu test_qga_guest_exec_merged); 10993dab9fa1SMarc-André Lureau g_test_add_data_func("/qga/guest-exec-invalid", &fix, 11003dab9fa1SMarc-André Lureau test_qga_guest_exec_invalid); 1101339ca68bSTomáš Golembiovský g_test_add_data_func("/qga/guest-get-osinfo", &fix, 1102339ca68bSTomáš Golembiovský test_qga_guest_get_osinfo); 1103509b97fdSTomáš Golembiovský g_test_add_data_func("/qga/guest-get-host-name", &fix, 1104509b97fdSTomáš Golembiovský test_qga_guest_get_host_name); 1105509b97fdSTomáš Golembiovský g_test_add_data_func("/qga/guest-get-timezone", &fix, 1106509b97fdSTomáš Golembiovský test_qga_guest_get_timezone); 1107509b97fdSTomáš Golembiovský g_test_add_data_func("/qga/guest-get-users", &fix, 1108509b97fdSTomáš Golembiovský test_qga_guest_get_users); 110962c39b30SMarc-André Lureau 111062c39b30SMarc-André Lureau ret = g_test_run(); 111162c39b30SMarc-André Lureau 111262c39b30SMarc-André Lureau fixture_tear_down(&fix, NULL); 111362c39b30SMarc-André Lureau 111462c39b30SMarc-André Lureau return ret; 111562c39b30SMarc-André Lureau } 1116