tor/src/test/test_dispatch.c

279 lines
5.8 KiB
C
Raw Normal View History

/* Copyright (c) 2018-2021, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DISPATCH_NEW_PRIVATE
#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;
static void
test_dispatch_max_in_u16_sl(void *arg)
{
(void)arg;
smartlist_t *sl = smartlist_new();
uint16_t nums[] = { 10, 20, 30 };
tt_int_op(-1, OP_EQ, max_in_u16_sl(sl, -1));
smartlist_add(sl, NULL);
tt_int_op(-1, OP_EQ, max_in_u16_sl(sl, -1));
smartlist_add(sl, &nums[1]);
tt_int_op(20, OP_EQ, max_in_u16_sl(sl, -1));
smartlist_add(sl, &nums[0]);
tt_int_op(20, OP_EQ, max_in_u16_sl(sl, -1));
smartlist_add(sl, NULL);
tt_int_op(20, OP_EQ, max_in_u16_sl(sl, -1));
smartlist_add(sl, &nums[2]);
tt_int_op(30, OP_EQ, max_in_u16_sl(sl, -1));
done:
smartlist_free(sl);
}
/* 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 receiver; 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);
}
Make all our struct names end with "_t". This is an automated commit, generated by this command: ./scripts/maint/rename_c_identifier.py \ address_ttl_s address_ttl_t \ aes_cnt_cipher aes_cnt_cipher_t \ authchallenge_data_s authchallenge_data_t \ authenticate_data_s authenticate_data_t \ cached_bw_event_s cached_bw_event_t \ cbuf cbuf_t \ cell_ewma_s cell_ewma_t \ certs_data_s certs_data_t \ channel_idmap_entry_s channel_idmap_entry_t \ channel_listener_s channel_listener_t \ channel_s channel_t \ channel_tls_s channel_tls_t \ circuit_build_times_s circuit_build_times_t \ circuit_muxinfo_s circuit_muxinfo_t \ circuitmux_policy_circ_data_s circuitmux_policy_circ_data_t \ circuitmux_policy_data_s circuitmux_policy_data_t \ circuitmux_policy_s circuitmux_policy_t \ circuitmux_s circuitmux_t \ coord coord_t \ cpuworker_job_u cpuworker_job_u_t \ cv_testinfo_s cv_testinfo_t \ ddmap_entry_s ddmap_entry_t \ dircollator_s dircollator_t \ dist_ops dist_ops_t \ ecdh_work_s ecdh_work_t \ ewma_policy_circ_data_s ewma_policy_circ_data_t \ ewma_policy_data_s ewma_policy_data_t \ fp_pair_map_entry_s fp_pair_map_entry_t \ fp_pair_map_s fp_pair_map_t \ guard_selection_s guard_selection_t \ mbw_cache_entry_s mbw_cache_entry_t \ outbuf_table_ent_s outbuf_table_ent_t \ queued_event_s queued_event_t \ replyqueue_s replyqueue_t \ rsa_work_s rsa_work_t \ sandbox_cfg_elem sandbox_cfg_elem_t \ scheduler_s scheduler_t \ smp_param smp_param_t \ socket_table_ent_s socket_table_ent_t \ state_s state_t \ threadpool_s threadpool_t \ timeout_cb timeout_cb_t \ tor_libevent_cfg tor_libevent_cfg_t \ tor_threadlocal_s tor_threadlocal_t \ url_table_ent_s url_table_ent_t \ worker_state_s worker_state_t \ workerthread_s workerthread_t \ workqueue_entry_s workqueue_entry_t
2019-11-07 14:41:22 +01:00
struct coord_t { 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;
Make all our struct names end with "_t". This is an automated commit, generated by this command: ./scripts/maint/rename_c_identifier.py \ address_ttl_s address_ttl_t \ aes_cnt_cipher aes_cnt_cipher_t \ authchallenge_data_s authchallenge_data_t \ authenticate_data_s authenticate_data_t \ cached_bw_event_s cached_bw_event_t \ cbuf cbuf_t \ cell_ewma_s cell_ewma_t \ certs_data_s certs_data_t \ channel_idmap_entry_s channel_idmap_entry_t \ channel_listener_s channel_listener_t \ channel_s channel_t \ channel_tls_s channel_tls_t \ circuit_build_times_s circuit_build_times_t \ circuit_muxinfo_s circuit_muxinfo_t \ circuitmux_policy_circ_data_s circuitmux_policy_circ_data_t \ circuitmux_policy_data_s circuitmux_policy_data_t \ circuitmux_policy_s circuitmux_policy_t \ circuitmux_s circuitmux_t \ coord coord_t \ cpuworker_job_u cpuworker_job_u_t \ cv_testinfo_s cv_testinfo_t \ ddmap_entry_s ddmap_entry_t \ dircollator_s dircollator_t \ dist_ops dist_ops_t \ ecdh_work_s ecdh_work_t \ ewma_policy_circ_data_s ewma_policy_circ_data_t \ ewma_policy_data_s ewma_policy_data_t \ fp_pair_map_entry_s fp_pair_map_entry_t \ fp_pair_map_s fp_pair_map_t \ guard_selection_s guard_selection_t \ mbw_cache_entry_s mbw_cache_entry_t \ outbuf_table_ent_s outbuf_table_ent_t \ queued_event_s queued_event_t \ replyqueue_s replyqueue_t \ rsa_work_s rsa_work_t \ sandbox_cfg_elem sandbox_cfg_elem_t \ scheduler_s scheduler_t \ smp_param smp_param_t \ socket_table_ent_s socket_table_ent_t \ state_s state_t \ threadpool_s threadpool_t \ timeout_cb timeout_cb_t \ tor_libevent_cfg tor_libevent_cfg_t \ tor_threadlocal_s tor_threadlocal_t \ url_table_ent_s url_table_ent_t \ worker_state_s worker_state_t \ workerthread_s workerthread_t \ workqueue_entry_s workqueue_entry_t
2019-11-07 14:41:22 +01:00
struct coord_t *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);
Make all our struct names end with "_t". This is an automated commit, generated by this command: ./scripts/maint/rename_c_identifier.py \ address_ttl_s address_ttl_t \ aes_cnt_cipher aes_cnt_cipher_t \ authchallenge_data_s authchallenge_data_t \ authenticate_data_s authenticate_data_t \ cached_bw_event_s cached_bw_event_t \ cbuf cbuf_t \ cell_ewma_s cell_ewma_t \ certs_data_s certs_data_t \ channel_idmap_entry_s channel_idmap_entry_t \ channel_listener_s channel_listener_t \ channel_s channel_t \ channel_tls_s channel_tls_t \ circuit_build_times_s circuit_build_times_t \ circuit_muxinfo_s circuit_muxinfo_t \ circuitmux_policy_circ_data_s circuitmux_policy_circ_data_t \ circuitmux_policy_data_s circuitmux_policy_data_t \ circuitmux_policy_s circuitmux_policy_t \ circuitmux_s circuitmux_t \ coord coord_t \ cpuworker_job_u cpuworker_job_u_t \ cv_testinfo_s cv_testinfo_t \ ddmap_entry_s ddmap_entry_t \ dircollator_s dircollator_t \ dist_ops dist_ops_t \ ecdh_work_s ecdh_work_t \ ewma_policy_circ_data_s ewma_policy_circ_data_t \ ewma_policy_data_s ewma_policy_data_t \ fp_pair_map_entry_s fp_pair_map_entry_t \ fp_pair_map_s fp_pair_map_t \ guard_selection_s guard_selection_t \ mbw_cache_entry_s mbw_cache_entry_t \ outbuf_table_ent_s outbuf_table_ent_t \ queued_event_s queued_event_t \ replyqueue_s replyqueue_t \ rsa_work_s rsa_work_t \ sandbox_cfg_elem sandbox_cfg_elem_t \ scheduler_s scheduler_t \ smp_param smp_param_t \ socket_table_ent_s socket_table_ent_t \ state_s state_t \ threadpool_s threadpool_t \ timeout_cb timeout_cb_t \ tor_libevent_cfg tor_libevent_cfg_t \ tor_threadlocal_s tor_threadlocal_t \ url_table_ent_s url_table_ent_t \ worker_state_s worker_state_t \ workerthread_s workerthread_t \ workqueue_entry_s workqueue_entry_t
2019-11-07 14:41:22 +01:00
struct coord_t *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(max_in_u16_sl),
T(empty),
T(simple),
T(no_recipient),
T(with_types),
T(bad_type_setup),
END_OF_TESTCASES
};