qom-test.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * QTest testcase for QOM
  3. *
  4. * Copyright (c) 2013 SUSE LINUX Products GmbH
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  7. * See the COPYING file in the top-level directory.
  8. */
  9. #include "qemu/osdep.h"
  10. #include "qemu-common.h"
  11. #include "qapi/qmp/qdict.h"
  12. #include "qapi/qmp/qlist.h"
  13. #include "qemu/cutils.h"
  14. #include "libqtest.h"
  15. static const char *blacklist_x86[] = {
  16. "xenfv", "xenpv", NULL
  17. };
  18. static const struct {
  19. const char *arch;
  20. const char **machine;
  21. } blacklists[] = {
  22. { "i386", blacklist_x86 },
  23. { "x86_64", blacklist_x86 },
  24. };
  25. static bool is_blacklisted(const char *arch, const char *mach)
  26. {
  27. int i;
  28. const char **p;
  29. for (i = 0; i < ARRAY_SIZE(blacklists); i++) {
  30. if (!strcmp(blacklists[i].arch, arch)) {
  31. for (p = blacklists[i].machine; *p; p++) {
  32. if (!strcmp(*p, mach)) {
  33. return true;
  34. }
  35. }
  36. }
  37. }
  38. return false;
  39. }
  40. static void test_properties(QTestState *qts, const char *path, bool recurse)
  41. {
  42. char *child_path;
  43. QDict *response, *tuple, *tmp;
  44. QList *list;
  45. QListEntry *entry;
  46. g_test_message("Obtaining properties of %s", path);
  47. response = qtest_qmp(qts, "{ 'execute': 'qom-list',"
  48. " 'arguments': { 'path': %s } }", path);
  49. g_assert(response);
  50. if (!recurse) {
  51. qobject_unref(response);
  52. return;
  53. }
  54. g_assert(qdict_haskey(response, "return"));
  55. list = qobject_to(QList, qdict_get(response, "return"));
  56. QLIST_FOREACH_ENTRY(list, entry) {
  57. tuple = qobject_to(QDict, qlist_entry_obj(entry));
  58. bool is_child = strstart(qdict_get_str(tuple, "type"), "child<", NULL);
  59. bool is_link = strstart(qdict_get_str(tuple, "type"), "link<", NULL);
  60. if (is_child || is_link) {
  61. child_path = g_strdup_printf("%s/%s",
  62. path, qdict_get_str(tuple, "name"));
  63. test_properties(qts, child_path, is_child);
  64. g_free(child_path);
  65. } else {
  66. const char *prop = qdict_get_str(tuple, "name");
  67. g_test_message("Testing property %s.%s", path, prop);
  68. tmp = qtest_qmp(qts,
  69. "{ 'execute': 'qom-get',"
  70. " 'arguments': { 'path': %s, 'property': %s } }",
  71. path, prop);
  72. /* qom-get may fail but should not, e.g., segfault. */
  73. g_assert(tmp);
  74. qobject_unref(tmp);
  75. }
  76. }
  77. qobject_unref(response);
  78. }
  79. static void test_machine(gconstpointer data)
  80. {
  81. const char *machine = data;
  82. QDict *response;
  83. QTestState *qts;
  84. qts = qtest_initf("-machine %s", machine);
  85. test_properties(qts, "/machine", true);
  86. response = qtest_qmp(qts, "{ 'execute': 'quit' }");
  87. g_assert(qdict_haskey(response, "return"));
  88. qobject_unref(response);
  89. qtest_quit(qts);
  90. g_free((void *)machine);
  91. }
  92. static void add_machine_test_case(const char *mname)
  93. {
  94. const char *arch = qtest_get_arch();
  95. if (!is_blacklisted(arch, mname)) {
  96. char *path = g_strdup_printf("qom/%s", mname);
  97. qtest_add_data_func(path, g_strdup(mname), test_machine);
  98. g_free(path);
  99. }
  100. }
  101. int main(int argc, char **argv)
  102. {
  103. g_test_init(&argc, &argv, NULL);
  104. qtest_cb_for_every_machine(add_machine_test_case, g_test_quick());
  105. return g_test_run();
  106. }