123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- /* Copyright (c) 2018, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- #define DISPATCH_PRIVATE
- #include "test/test.h"
- #include "lib/dispatch/dispatch.h"
- #include "lib/dispatch/dispatch_cfg.h"
- #include "lib/dispatch/dispatch_st.h"
- #include "lib/dispatch/msgtypes.h"
- #include "lib/log/escape.h"
- #include "lib/malloc/malloc.h"
- #include "lib/string/printf.h"
- #include <stdio.h>
- #include <string.h>
- static dispatch_t *dispatcher_in_use=NULL;
- /* Construct an empty dispatch_t. */
- static void
- test_dispatch_empty(void *arg)
- {
- (void)arg;
- dispatch_t *d=NULL;
- dispatch_cfg_t *cfg=NULL;
- cfg = dcfg_new();
- d = dispatch_new(cfg);
- tt_assert(d);
- done:
- dispatch_free(d);
- dcfg_free(cfg);
- }
- static int total_recv1_simple = 0;
- static int total_recv2_simple = 0;
- static void
- simple_recv1(const msg_t *m)
- {
- total_recv1_simple += m->aux_data__.u64;
- }
- static char *recv2_received = NULL;
- static void
- simple_recv2(const msg_t *m)
- {
- tor_free(recv2_received);
- recv2_received = dispatch_fmt_msg_data(dispatcher_in_use, m);
- total_recv2_simple += m->aux_data__.u64*10;
- }
- /* Construct a dispatch_t with two messages, make sure that they both get
- * delivered. */
- static void
- test_dispatch_simple(void *arg)
- {
- (void)arg;
- dispatch_t *d=NULL;
- dispatch_cfg_t *cfg=NULL;
- int r;
- cfg = dcfg_new();
- r = dcfg_msg_set_type(cfg,0,0);
- r += dcfg_msg_set_chan(cfg,0,0);
- r += dcfg_add_recv(cfg,0,1,simple_recv1);
- r += dcfg_msg_set_type(cfg,1,0);
- r += dcfg_msg_set_chan(cfg,1,0);
- r += dcfg_add_recv(cfg,1,1,simple_recv2);
- r += dcfg_add_recv(cfg,1,1,simple_recv2); /* second copy */
- tt_int_op(r, OP_EQ, 0);
- d = dispatch_new(cfg);
- tt_assert(d);
- dispatcher_in_use = d;
- msg_aux_data_t data = {.u64 = 7};
- r = dispatch_send(d, 99, 0, 0, 0, data);
- tt_int_op(r, OP_EQ, 0);
- tt_int_op(total_recv1_simple, OP_EQ, 0);
- r = dispatch_flush(d, 0, INT_MAX);
- tt_int_op(r, OP_EQ, 0);
- tt_int_op(total_recv1_simple, OP_EQ, 7);
- tt_int_op(total_recv2_simple, OP_EQ, 0);
- total_recv1_simple = 0;
- r = dispatch_send(d, 99, 0, 1, 0, data);
- tt_int_op(r, OP_EQ, 0);
- r = dispatch_flush(d, 0, INT_MAX);
- tt_int_op(total_recv1_simple, OP_EQ, 0);
- tt_int_op(total_recv2_simple, OP_EQ, 140);
- tt_str_op(recv2_received, OP_EQ, "<>"); // no format function was set.
- done:
- dispatch_free(d);
- dcfg_free(cfg);
- tor_free(recv2_received);
- }
- /* Construct a dispatch_t with a message and no reciever; make sure that it
- * gets dropped properly. */
- static void
- test_dispatch_no_recipient(void *arg)
- {
- (void)arg;
- dispatch_t *d=NULL;
- dispatch_cfg_t *cfg=NULL;
- int r;
- cfg = dcfg_new();
- r = dcfg_msg_set_type(cfg,0,0);
- r += dcfg_msg_set_chan(cfg,0,0);
- tt_int_op(r, OP_EQ, 0);
- d = dispatch_new(cfg);
- tt_assert(d);
- dispatcher_in_use = d;
- msg_aux_data_t data = { .u64 = 7};
- r = dispatch_send(d, 99, 0, 0, 0, data);
- tt_int_op(r, OP_EQ, 0);
- r = dispatch_flush(d, 0, INT_MAX);
- tt_int_op(r, OP_EQ, 0);
- done:
- dispatch_free(d);
- dcfg_free(cfg);
- }
- struct coord { int x; int y; };
- static void
- free_coord(msg_aux_data_t d)
- {
- tor_free(d.ptr);
- }
- static char *
- fmt_coord(msg_aux_data_t d)
- {
- char *v;
- struct coord *c = d.ptr;
- tor_asprintf(&v, "[%d, %d]", c->x, c->y);
- return v;
- }
- static dispatch_typefns_t coord_fns = {
- .fmt_fn = fmt_coord,
- .free_fn = free_coord,
- };
- static void
- alert_run_immediate(dispatch_t *d, channel_id_t ch, void *arg)
- {
- (void)arg;
- dispatch_flush(d, ch, INT_MAX);
- }
- static char *received_data=NULL;
- static void
- recv_typed_data(const msg_t *m)
- {
- tor_free(received_data);
- received_data = dispatch_fmt_msg_data(dispatcher_in_use, m);
- }
- static void
- test_dispatch_with_types(void *arg)
- {
- (void)arg;
- dispatch_t *d=NULL;
- dispatch_cfg_t *cfg=NULL;
- int r;
- cfg = dcfg_new();
- r = dcfg_msg_set_type(cfg,5,3);
- r += dcfg_msg_set_chan(cfg,5,2);
- r += dcfg_add_recv(cfg,5,0,recv_typed_data);
- r += dcfg_type_set_fns(cfg,3,&coord_fns);
- tt_int_op(r, OP_EQ, 0);
- d = dispatch_new(cfg);
- tt_assert(d);
- dispatcher_in_use = d;
- /* Make this message get run immediately. */
- r = dispatch_set_alert_fn(d, 2, alert_run_immediate, NULL);
- tt_int_op(r, OP_EQ, 0);
- struct coord *xy = tor_malloc(sizeof(*xy));
- xy->x = 13;
- xy->y = 37;
- msg_aux_data_t data = {.ptr = xy};
- r = dispatch_send(d, 99/*sender*/, 2/*channel*/, 5/*msg*/, 3/*type*/, data);
- tt_int_op(r, OP_EQ, 0);
- tt_str_op(received_data, OP_EQ, "[13, 37]");
- done:
- dispatch_free(d);
- dcfg_free(cfg);
- tor_free(received_data);
- dispatcher_in_use = NULL;
- }
- static void
- test_dispatch_bad_type_setup(void *arg)
- {
- (void)arg;
- static dispatch_typefns_t fns;
- dispatch_cfg_t *cfg = dcfg_new();
- tt_int_op(0, OP_EQ, dcfg_type_set_fns(cfg, 7, &coord_fns));
- fns = coord_fns;
- fns.fmt_fn = NULL;
- tt_int_op(-1, OP_EQ, dcfg_type_set_fns(cfg, 7, &fns));
- fns = coord_fns;
- fns.free_fn = NULL;
- tt_int_op(-1, OP_EQ, dcfg_type_set_fns(cfg, 7, &fns));
- fns = coord_fns;
- tt_int_op(0, OP_EQ, dcfg_type_set_fns(cfg, 7, &fns));
- done:
- dcfg_free(cfg);
- }
- #define T(name) \
- { #name, test_dispatch_ ## name, TT_FORK, NULL, NULL }
- struct testcase_t dispatch_tests[] = {
- T(empty),
- T(simple),
- T(no_recipient),
- T(with_types),
- T(bad_type_setup),
- END_OF_TESTCASES
- };
|