test_dispatch.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* Copyright (c) 2018, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #define DISPATCH_PRIVATE
  4. #include "test/test.h"
  5. #include "lib/dispatch/dispatch.h"
  6. #include "lib/dispatch/dispatch_cfg.h"
  7. #include "lib/dispatch/dispatch_st.h"
  8. #include "lib/dispatch/msgtypes.h"
  9. #include "lib/log/escape.h"
  10. #include "lib/malloc/malloc.h"
  11. #include "lib/string/printf.h"
  12. #include <stdio.h>
  13. #include <string.h>
  14. /* Construct an empty dispatch_t. */
  15. static void
  16. test_dispatch_empty(void *arg)
  17. {
  18. (void)arg;
  19. dispatch_t *d=NULL;
  20. dispatch_cfg_t *cfg=NULL;
  21. cfg = dcfg_new();
  22. d = dispatch_new(cfg);
  23. tt_assert(d);
  24. done:
  25. dispatch_free(d);
  26. dcfg_free(cfg);
  27. }
  28. static int total_recv1_simple = 0;
  29. static int total_recv2_simple = 0;
  30. static void
  31. simple_recv1(const msg_t *m)
  32. {
  33. total_recv1_simple += m->aux_data__.u64;
  34. }
  35. static void
  36. simple_recv2(const msg_t *m)
  37. {
  38. total_recv2_simple += m->aux_data__.u64*10;
  39. }
  40. /* Construct a dispatch_t with two messages, make sure that they both get
  41. * delivered. */
  42. static void
  43. test_dispatch_simple(void *arg)
  44. {
  45. (void)arg;
  46. dispatch_t *d=NULL;
  47. dispatch_cfg_t *cfg=NULL;
  48. int r;
  49. cfg = dcfg_new();
  50. r = dcfg_msg_set_type(cfg,0,0);
  51. r += dcfg_msg_set_chan(cfg,0,0);
  52. r += dcfg_add_recv(cfg,0,1,simple_recv1);
  53. r += dcfg_msg_set_type(cfg,1,0);
  54. r += dcfg_msg_set_chan(cfg,1,0);
  55. r += dcfg_add_recv(cfg,1,1,simple_recv2);
  56. r += dcfg_add_recv(cfg,1,1,simple_recv2); /* second copy */
  57. tt_int_op(r, OP_EQ, 0);
  58. d = dispatch_new(cfg);
  59. tt_assert(d);
  60. msg_aux_data_t data = {.u64 = 7};
  61. r = dispatch_send(d, 99, 0, 0, 0, data);
  62. tt_int_op(r, OP_EQ, 0);
  63. tt_int_op(total_recv1_simple, OP_EQ, 0);
  64. r = dispatch_flush(d, 0, INT_MAX);
  65. tt_int_op(r, OP_EQ, 0);
  66. tt_int_op(total_recv1_simple, OP_EQ, 7);
  67. tt_int_op(total_recv2_simple, OP_EQ, 0);
  68. total_recv1_simple = 0;
  69. r = dispatch_send(d, 99, 0, 1, 0, data);
  70. tt_int_op(r, OP_EQ, 0);
  71. r = dispatch_flush(d, 0, INT_MAX);
  72. tt_int_op(total_recv1_simple, OP_EQ, 0);
  73. tt_int_op(total_recv2_simple, OP_EQ, 140);
  74. done:
  75. dispatch_free(d);
  76. dcfg_free(cfg);
  77. }
  78. struct coord { int x; int y; };
  79. static void
  80. free_coord(msg_aux_data_t d)
  81. {
  82. tor_free(d.ptr);
  83. }
  84. static char *
  85. fmt_coord(msg_aux_data_t d)
  86. {
  87. char *v;
  88. struct coord *c = d.ptr;
  89. tor_asprintf(&v, "[%d, %d]", c->x, c->y);
  90. return v;
  91. }
  92. static dispatch_typefns_t coord_fns = {
  93. .fmt_fn = fmt_coord,
  94. .free_fn = free_coord,
  95. };
  96. static void
  97. alert_run_immediate(dispatch_t *d, channel_id_t ch, void *arg)
  98. {
  99. (void)arg;
  100. dispatch_flush(d, ch, INT_MAX);
  101. }
  102. static dispatch_t *dispatcher_in_use=NULL;
  103. static char *received_data=NULL;
  104. static void
  105. recv_typed_data(const msg_t *m)
  106. {
  107. tor_free(received_data);
  108. received_data = dispatch_fmt_msg_data(dispatcher_in_use, m);
  109. }
  110. static void
  111. test_dispatch_with_types(void *arg)
  112. {
  113. (void)arg;
  114. dispatch_t *d=NULL;
  115. dispatch_cfg_t *cfg=NULL;
  116. int r;
  117. cfg = dcfg_new();
  118. r = dcfg_msg_set_type(cfg,5,3);
  119. r += dcfg_msg_set_chan(cfg,5,2);
  120. r += dcfg_add_recv(cfg,5,0,recv_typed_data);
  121. r += dcfg_type_set_fns(cfg,3,&coord_fns);
  122. tt_int_op(r, OP_EQ, 0);
  123. d = dispatch_new(cfg);
  124. tt_assert(d);
  125. dispatcher_in_use = d;
  126. /* Make this message get run immediately. */
  127. r = dispatch_set_alert_fn(d, 2, alert_run_immediate, NULL);
  128. tt_int_op(r, OP_EQ, 0);
  129. struct coord *xy = tor_malloc(sizeof(*xy));
  130. xy->x = 13;
  131. xy->y = 37;
  132. msg_aux_data_t data = {.ptr = xy};
  133. r = dispatch_send(d, 99/*sender*/, 2/*channel*/, 5/*msg*/, 3/*type*/, data);
  134. tt_int_op(r, OP_EQ, 0);
  135. tt_str_op(received_data, OP_EQ, "[13, 37]");
  136. done:
  137. dispatch_free(d);
  138. dcfg_free(cfg);
  139. tor_free(received_data);
  140. dispatcher_in_use = NULL;
  141. }
  142. #define T(name) \
  143. { #name, test_dispatch_ ## name, TT_FORK, NULL, NULL }
  144. struct testcase_t dispatch_tests[] = {
  145. T(empty),
  146. T(simple),
  147. T(with_types),
  148. END_OF_TESTCASES
  149. };