LCOV - code coverage report
Current view: top level - test - test_dispatch.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 156 156 100.0 %
Date: 2021-11-24 03:28:48 Functions: 12 12 100.0 %

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

Generated by: LCOV version 1.14