test_dispatch.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /* Copyright (c) 2018, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define DISPATCH_NEW_PRIVATE
  4. #define DISPATCH_PRIVATE
  5. #include "test/test.h"
  6. #include "lib/dispatch/dispatch.h"
  7. #include "lib/dispatch/dispatch_cfg.h"
  8. #include "lib/dispatch/dispatch_st.h"
  9. #include "lib/dispatch/msgtypes.h"
  10. #include "lib/log/escape.h"
  11. #include "lib/malloc/malloc.h"
  12. #include "lib/string/printf.h"
  13. #include <stdio.h>
  14. #include <string.h>
  15. static dispatch_t *dispatcher_in_use=NULL;
  16. static void
  17. test_dispatch_max_in_u16_sl(void *arg)
  18. {
  19. (void)arg;
  20. smartlist_t *sl = smartlist_new();
  21. uint16_t nums[] = { 10, 20, 30 };
  22. tt_int_op(-1, OP_EQ, max_in_u16_sl(sl, -1));
  23. smartlist_add(sl, NULL);
  24. tt_int_op(-1, OP_EQ, max_in_u16_sl(sl, -1));
  25. smartlist_add(sl, &nums[1]);
  26. tt_int_op(20, OP_EQ, max_in_u16_sl(sl, -1));
  27. smartlist_add(sl, &nums[0]);
  28. tt_int_op(20, OP_EQ, max_in_u16_sl(sl, -1));
  29. smartlist_add(sl, NULL);
  30. tt_int_op(20, OP_EQ, max_in_u16_sl(sl, -1));
  31. smartlist_add(sl, &nums[2]);
  32. tt_int_op(30, OP_EQ, max_in_u16_sl(sl, -1));
  33. done:
  34. smartlist_free(sl);
  35. }
  36. /* Construct an empty dispatch_t. */
  37. static void
  38. test_dispatch_empty(void *arg)
  39. {
  40. (void)arg;
  41. dispatch_t *d=NULL;
  42. dispatch_cfg_t *cfg=NULL;
  43. cfg = dcfg_new();
  44. d = dispatch_new(cfg);
  45. tt_assert(d);
  46. done:
  47. dispatch_free(d);
  48. dcfg_free(cfg);
  49. }
  50. static int total_recv1_simple = 0;
  51. static int total_recv2_simple = 0;
  52. static void
  53. simple_recv1(const msg_t *m)
  54. {
  55. total_recv1_simple += m->aux_data__.u64;
  56. }
  57. static char *recv2_received = NULL;
  58. static void
  59. simple_recv2(const msg_t *m)
  60. {
  61. tor_free(recv2_received);
  62. recv2_received = dispatch_fmt_msg_data(dispatcher_in_use, m);
  63. total_recv2_simple += m->aux_data__.u64*10;
  64. }
  65. /* Construct a dispatch_t with two messages, make sure that they both get
  66. * delivered. */
  67. static void
  68. test_dispatch_simple(void *arg)
  69. {
  70. (void)arg;
  71. dispatch_t *d=NULL;
  72. dispatch_cfg_t *cfg=NULL;
  73. int r;
  74. cfg = dcfg_new();
  75. r = dcfg_msg_set_type(cfg,0,0);
  76. r += dcfg_msg_set_chan(cfg,0,0);
  77. r += dcfg_add_recv(cfg,0,1,simple_recv1);
  78. r += dcfg_msg_set_type(cfg,1,0);
  79. r += dcfg_msg_set_chan(cfg,1,0);
  80. r += dcfg_add_recv(cfg,1,1,simple_recv2);
  81. r += dcfg_add_recv(cfg,1,1,simple_recv2); /* second copy */
  82. tt_int_op(r, OP_EQ, 0);
  83. d = dispatch_new(cfg);
  84. tt_assert(d);
  85. dispatcher_in_use = d;
  86. msg_aux_data_t data = {.u64 = 7};
  87. r = dispatch_send(d, 99, 0, 0, 0, data);
  88. tt_int_op(r, OP_EQ, 0);
  89. tt_int_op(total_recv1_simple, OP_EQ, 0);
  90. r = dispatch_flush(d, 0, INT_MAX);
  91. tt_int_op(r, OP_EQ, 0);
  92. tt_int_op(total_recv1_simple, OP_EQ, 7);
  93. tt_int_op(total_recv2_simple, OP_EQ, 0);
  94. total_recv1_simple = 0;
  95. r = dispatch_send(d, 99, 0, 1, 0, data);
  96. tt_int_op(r, OP_EQ, 0);
  97. r = dispatch_flush(d, 0, INT_MAX);
  98. tt_int_op(total_recv1_simple, OP_EQ, 0);
  99. tt_int_op(total_recv2_simple, OP_EQ, 140);
  100. tt_str_op(recv2_received, OP_EQ, "<>"); // no format function was set.
  101. done:
  102. dispatch_free(d);
  103. dcfg_free(cfg);
  104. tor_free(recv2_received);
  105. }
  106. /* Construct a dispatch_t with a message and no reciever; make sure that it
  107. * gets dropped properly. */
  108. static void
  109. test_dispatch_no_recipient(void *arg)
  110. {
  111. (void)arg;
  112. dispatch_t *d=NULL;
  113. dispatch_cfg_t *cfg=NULL;
  114. int r;
  115. cfg = dcfg_new();
  116. r = dcfg_msg_set_type(cfg,0,0);
  117. r += dcfg_msg_set_chan(cfg,0,0);
  118. tt_int_op(r, OP_EQ, 0);
  119. d = dispatch_new(cfg);
  120. tt_assert(d);
  121. dispatcher_in_use = d;
  122. msg_aux_data_t data = { .u64 = 7};
  123. r = dispatch_send(d, 99, 0, 0, 0, data);
  124. tt_int_op(r, OP_EQ, 0);
  125. r = dispatch_flush(d, 0, INT_MAX);
  126. tt_int_op(r, OP_EQ, 0);
  127. done:
  128. dispatch_free(d);
  129. dcfg_free(cfg);
  130. }
  131. struct coord { int x; int y; };
  132. static void
  133. free_coord(msg_aux_data_t d)
  134. {
  135. tor_free(d.ptr);
  136. }
  137. static char *
  138. fmt_coord(msg_aux_data_t d)
  139. {
  140. char *v;
  141. struct coord *c = d.ptr;
  142. tor_asprintf(&v, "[%d, %d]", c->x, c->y);
  143. return v;
  144. }
  145. static dispatch_typefns_t coord_fns = {
  146. .fmt_fn = fmt_coord,
  147. .free_fn = free_coord,
  148. };
  149. static void
  150. alert_run_immediate(dispatch_t *d, channel_id_t ch, void *arg)
  151. {
  152. (void)arg;
  153. dispatch_flush(d, ch, INT_MAX);
  154. }
  155. static char *received_data=NULL;
  156. static void
  157. recv_typed_data(const msg_t *m)
  158. {
  159. tor_free(received_data);
  160. received_data = dispatch_fmt_msg_data(dispatcher_in_use, m);
  161. }
  162. static void
  163. test_dispatch_with_types(void *arg)
  164. {
  165. (void)arg;
  166. dispatch_t *d=NULL;
  167. dispatch_cfg_t *cfg=NULL;
  168. int r;
  169. cfg = dcfg_new();
  170. r = dcfg_msg_set_type(cfg,5,3);
  171. r += dcfg_msg_set_chan(cfg,5,2);
  172. r += dcfg_add_recv(cfg,5,0,recv_typed_data);
  173. r += dcfg_type_set_fns(cfg,3,&coord_fns);
  174. tt_int_op(r, OP_EQ, 0);
  175. d = dispatch_new(cfg);
  176. tt_assert(d);
  177. dispatcher_in_use = d;
  178. /* Make this message get run immediately. */
  179. r = dispatch_set_alert_fn(d, 2, alert_run_immediate, NULL);
  180. tt_int_op(r, OP_EQ, 0);
  181. struct coord *xy = tor_malloc(sizeof(*xy));
  182. xy->x = 13;
  183. xy->y = 37;
  184. msg_aux_data_t data = {.ptr = xy};
  185. r = dispatch_send(d, 99/*sender*/, 2/*channel*/, 5/*msg*/, 3/*type*/, data);
  186. tt_int_op(r, OP_EQ, 0);
  187. tt_str_op(received_data, OP_EQ, "[13, 37]");
  188. done:
  189. dispatch_free(d);
  190. dcfg_free(cfg);
  191. tor_free(received_data);
  192. dispatcher_in_use = NULL;
  193. }
  194. static void
  195. test_dispatch_bad_type_setup(void *arg)
  196. {
  197. (void)arg;
  198. static dispatch_typefns_t fns;
  199. dispatch_cfg_t *cfg = dcfg_new();
  200. tt_int_op(0, OP_EQ, dcfg_type_set_fns(cfg, 7, &coord_fns));
  201. fns = coord_fns;
  202. fns.fmt_fn = NULL;
  203. tt_int_op(-1, OP_EQ, dcfg_type_set_fns(cfg, 7, &fns));
  204. fns = coord_fns;
  205. fns.free_fn = NULL;
  206. tt_int_op(-1, OP_EQ, dcfg_type_set_fns(cfg, 7, &fns));
  207. fns = coord_fns;
  208. tt_int_op(0, OP_EQ, dcfg_type_set_fns(cfg, 7, &fns));
  209. done:
  210. dcfg_free(cfg);
  211. }
  212. #define T(name) \
  213. { #name, test_dispatch_ ## name, TT_FORK, NULL, NULL }
  214. struct testcase_t dispatch_tests[] = {
  215. T(max_in_u16_sl),
  216. T(empty),
  217. T(simple),
  218. T(no_recipient),
  219. T(with_types),
  220. T(bad_type_setup),
  221. END_OF_TESTCASES
  222. };