test-qmp-event.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * qapi event unit-tests.
  3. *
  4. * Copyright (c) 2014 Wenchao Xia
  5. *
  6. * Authors:
  7. * Wenchao Xia <wenchaoqemu@gmail.com>
  8. *
  9. * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  10. * See the COPYING.LIB file in the top-level directory.
  11. *
  12. */
  13. #include "qemu/osdep.h"
  14. #include "qemu-common.h"
  15. #include "qapi/error.h"
  16. #include "qapi/qmp/qbool.h"
  17. #include "qapi/qmp/qdict.h"
  18. #include "qapi/qmp/qnum.h"
  19. #include "qapi/qmp/qstring.h"
  20. #include "qapi/qmp-event.h"
  21. #include "test-qapi-events.h"
  22. #include "test-qapi-emit-events.h"
  23. typedef struct TestEventData {
  24. QDict *expect;
  25. } TestEventData;
  26. typedef struct QDictCmpData {
  27. QDict *expect;
  28. bool result;
  29. } QDictCmpData;
  30. TestEventData *test_event_data;
  31. static GMutex test_event_lock;
  32. /* Only compares bool, int, string */
  33. static
  34. void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque)
  35. {
  36. QObject *obj2;
  37. QDictCmpData d_new, *d = opaque;
  38. int64_t val1, val2;
  39. if (!d->result) {
  40. return;
  41. }
  42. obj2 = qdict_get(d->expect, key);
  43. if (!obj2) {
  44. d->result = false;
  45. return;
  46. }
  47. if (qobject_type(obj1) != qobject_type(obj2)) {
  48. d->result = false;
  49. return;
  50. }
  51. switch (qobject_type(obj1)) {
  52. case QTYPE_QBOOL:
  53. d->result = (qbool_get_bool(qobject_to(QBool, obj1)) ==
  54. qbool_get_bool(qobject_to(QBool, obj2)));
  55. return;
  56. case QTYPE_QNUM:
  57. g_assert(qnum_get_try_int(qobject_to(QNum, obj1), &val1));
  58. g_assert(qnum_get_try_int(qobject_to(QNum, obj2), &val2));
  59. d->result = val1 == val2;
  60. return;
  61. case QTYPE_QSTRING:
  62. d->result = g_strcmp0(qstring_get_str(qobject_to(QString, obj1)),
  63. qstring_get_str(qobject_to(QString, obj2))) == 0;
  64. return;
  65. case QTYPE_QDICT:
  66. d_new.expect = qobject_to(QDict, obj2);
  67. d_new.result = true;
  68. qdict_iter(qobject_to(QDict, obj1), qdict_cmp_do_simple, &d_new);
  69. d->result = d_new.result;
  70. return;
  71. default:
  72. abort();
  73. }
  74. }
  75. static bool qdict_cmp_simple(QDict *a, QDict *b)
  76. {
  77. QDictCmpData d;
  78. d.expect = b;
  79. d.result = true;
  80. qdict_iter(a, qdict_cmp_do_simple, &d);
  81. return d.result;
  82. }
  83. void test_qapi_event_emit(test_QAPIEvent event, QDict *d)
  84. {
  85. QDict *t;
  86. int64_t s, ms;
  87. /* Verify that we have timestamp, then remove it to compare other fields */
  88. t = qdict_get_qdict(d, "timestamp");
  89. g_assert(t);
  90. s = qdict_get_try_int(t, "seconds", -2);
  91. ms = qdict_get_try_int(t, "microseconds", -2);
  92. if (s == -1) {
  93. g_assert(ms == -1);
  94. } else {
  95. g_assert(s >= 0);
  96. g_assert(ms >= 0 && ms <= 999999);
  97. }
  98. g_assert(qdict_size(t) == 2);
  99. qdict_del(d, "timestamp");
  100. g_assert(qdict_cmp_simple(d, test_event_data->expect));
  101. }
  102. static void event_prepare(TestEventData *data,
  103. const void *unused)
  104. {
  105. /* Global variable test_event_data was used to pass the expectation, so
  106. test cases can't be executed at same time. */
  107. g_mutex_lock(&test_event_lock);
  108. data->expect = qdict_new();
  109. test_event_data = data;
  110. }
  111. static void event_teardown(TestEventData *data,
  112. const void *unused)
  113. {
  114. qobject_unref(data->expect);
  115. test_event_data = NULL;
  116. g_mutex_unlock(&test_event_lock);
  117. }
  118. static void event_test_add(const char *testpath,
  119. void (*test_func)(TestEventData *data,
  120. const void *user_data))
  121. {
  122. g_test_add(testpath, TestEventData, NULL, event_prepare, test_func,
  123. event_teardown);
  124. }
  125. /* Test cases */
  126. static void test_event_a(TestEventData *data,
  127. const void *unused)
  128. {
  129. QDict *d;
  130. d = data->expect;
  131. qdict_put_str(d, "event", "EVENT_A");
  132. qapi_event_send_event_a();
  133. }
  134. static void test_event_b(TestEventData *data,
  135. const void *unused)
  136. {
  137. QDict *d;
  138. d = data->expect;
  139. qdict_put_str(d, "event", "EVENT_B");
  140. qapi_event_send_event_b();
  141. }
  142. static void test_event_c(TestEventData *data,
  143. const void *unused)
  144. {
  145. QDict *d, *d_data, *d_b;
  146. UserDefOne b;
  147. b.integer = 2;
  148. b.string = g_strdup("test1");
  149. b.has_enum1 = false;
  150. d_b = qdict_new();
  151. qdict_put_int(d_b, "integer", 2);
  152. qdict_put_str(d_b, "string", "test1");
  153. d_data = qdict_new();
  154. qdict_put_int(d_data, "a", 1);
  155. qdict_put(d_data, "b", d_b);
  156. qdict_put_str(d_data, "c", "test2");
  157. d = data->expect;
  158. qdict_put_str(d, "event", "EVENT_C");
  159. qdict_put(d, "data", d_data);
  160. qapi_event_send_event_c(true, 1, true, &b, "test2");
  161. g_free(b.string);
  162. }
  163. /* Complex type */
  164. static void test_event_d(TestEventData *data,
  165. const void *unused)
  166. {
  167. UserDefOne struct1;
  168. EventStructOne a;
  169. QDict *d, *d_data, *d_a, *d_struct1;
  170. struct1.integer = 2;
  171. struct1.string = g_strdup("test1");
  172. struct1.has_enum1 = true;
  173. struct1.enum1 = ENUM_ONE_VALUE1;
  174. a.struct1 = &struct1;
  175. a.string = g_strdup("test2");
  176. a.has_enum2 = true;
  177. a.enum2 = ENUM_ONE_VALUE2;
  178. d_struct1 = qdict_new();
  179. qdict_put_int(d_struct1, "integer", 2);
  180. qdict_put_str(d_struct1, "string", "test1");
  181. qdict_put_str(d_struct1, "enum1", "value1");
  182. d_a = qdict_new();
  183. qdict_put(d_a, "struct1", d_struct1);
  184. qdict_put_str(d_a, "string", "test2");
  185. qdict_put_str(d_a, "enum2", "value2");
  186. d_data = qdict_new();
  187. qdict_put(d_data, "a", d_a);
  188. qdict_put_str(d_data, "b", "test3");
  189. qdict_put_str(d_data, "enum3", "value3");
  190. d = data->expect;
  191. qdict_put_str(d, "event", "EVENT_D");
  192. qdict_put(d, "data", d_data);
  193. qapi_event_send_event_d(&a, "test3", false, NULL, true, ENUM_ONE_VALUE3);
  194. g_free(struct1.string);
  195. g_free(a.string);
  196. }
  197. int main(int argc, char **argv)
  198. {
  199. g_test_init(&argc, &argv, NULL);
  200. event_test_add("/event/event_a", test_event_a);
  201. event_test_add("/event/event_b", test_event_b);
  202. event_test_add("/event/event_c", test_event_c);
  203. event_test_add("/event/event_d", test_event_d);
  204. g_test_run();
  205. return 0;
  206. }