void command_setup_channel(channel_t *chan) { tor_assert(chan); channel_set_cell_handlers(chan, command_process_cell, command_process_var_cell); }
/* Test inbound cell. The callstack is: * channel_process_cell() * -> chan->cell_handler() * * This test is about checking if we can process an inbound cell down to the * channel handler. */ static void test_channel_inbound_cell(void *arg) { channel_t *chan = NULL; cell_t *cell = NULL; int old_count; (void) arg; /* The channel will be freed so we need to hijack this so the scheduler * doesn't get confused. */ MOCK(scheduler_release_channel, scheduler_release_channel_mock); /* Accept cells to lower layer */ test_chan_accept_cells = 1; chan = new_fake_channel(); tt_assert(chan); /* Start it off in OPENING */ chan->state = CHANNEL_STATE_OPENING; /* Try to register it */ channel_register(chan); tt_int_op(chan->registered, OP_EQ, 1); /* Open it */ channel_change_state_open(chan); tt_int_op(chan->state, OP_EQ, CHANNEL_STATE_OPEN); tt_int_op(chan->has_been_open, OP_EQ, 1); /* Receive a cell now. */ cell = tor_malloc_zero(sizeof(*cell)); make_fake_cell(cell); old_count = test_chan_fixed_cells_recved; channel_process_cell(chan, cell); tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count); tt_assert(monotime_coarse_is_zero(&chan->timestamp_xfer)); tt_u64_op(chan->timestamp_active, OP_EQ, 0); tt_u64_op(chan->timestamp_recv, OP_EQ, 0); /* Setup incoming cell handlers. We don't care about var cell, the channel * layers is not handling those. */ channel_set_cell_handlers(chan, chan_test_cell_handler, NULL); tt_ptr_op(chan->cell_handler, OP_EQ, chan_test_cell_handler); /* Now process the cell, we should see it. */ old_count = test_chan_fixed_cells_recved; channel_process_cell(chan, cell); tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count + 1); /* We should have a series of timestamp set. */ tt_assert(!monotime_coarse_is_zero(&chan->timestamp_xfer)); tt_u64_op(chan->timestamp_active, OP_NE, 0); tt_u64_op(chan->timestamp_recv, OP_NE, 0); tt_assert(monotime_coarse_is_zero(&chan->next_padding_time)); tt_u64_op(chan->n_cells_recved, OP_EQ, 1); tt_u64_op(chan->n_bytes_recved, OP_EQ, get_cell_network_size(0)); /* Close it */ old_count = test_close_called; channel_mark_for_close(chan); tt_int_op(chan->state, OP_EQ, CHANNEL_STATE_CLOSING); tt_int_op(chan->reason_for_closing, OP_EQ, CHANNEL_CLOSE_REQUESTED); tt_int_op(test_close_called, OP_EQ, old_count + 1); /* This closes the channe so it calls in the scheduler, make sure of it. */ old_count = test_releases_count; chan_test_finish_close(chan); tt_int_op(test_releases_count, OP_EQ, old_count + 1); tt_int_op(chan->state, OP_EQ, CHANNEL_STATE_CLOSED); /* The channel will be free, lets make sure it is not accessible. */ uint64_t chan_id = chan->global_identifier; tt_ptr_op(channel_find_by_global_id(chan_id), OP_EQ, chan); channel_run_cleanup(); chan = channel_find_by_global_id(chan_id); tt_assert(chan == NULL); done: tor_free(cell); UNMOCK(scheduler_release_channel); }
static void test_channel_dumpstats(void *arg) { channel_t *ch = NULL; cell_t *cell = NULL; packed_cell_t *p_cell = NULL; int old_count; (void)arg; /* Mock these for duration of the test */ MOCK(scheduler_channel_doesnt_want_writes, scheduler_channel_doesnt_want_writes_mock); MOCK(scheduler_release_channel, scheduler_release_channel_mock); /* Set up a new fake channel */ ch = new_fake_channel(); tt_assert(ch); /* Try to register it */ channel_register(ch); tt_assert(ch->registered); /* Set up mock */ dump_statistics_mock_target = ch; dump_statistics_mock_matches = 0; MOCK(channel_dump_statistics, chan_test_channel_dump_statistics_mock); /* Call channel_dumpstats() */ channel_dumpstats(LOG_DEBUG); /* Assert that we hit the mock */ tt_int_op(dump_statistics_mock_matches, OP_EQ, 1); /* Close the channel */ channel_mark_for_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); /* Try again and hit the finished channel */ channel_dumpstats(LOG_DEBUG); tt_int_op(dump_statistics_mock_matches, OP_EQ, 2); channel_run_cleanup(); ch = NULL; /* Now we should hit nothing */ channel_dumpstats(LOG_DEBUG); tt_int_op(dump_statistics_mock_matches, OP_EQ, 2); /* Unmock */ UNMOCK(channel_dump_statistics); dump_statistics_mock_target = NULL; dump_statistics_mock_matches = 0; /* Now make another channel */ ch = new_fake_channel(); tt_assert(ch); channel_register(ch); tt_int_op(ch->registered, OP_EQ, 1); /* Lie about its age so dumpstats gets coverage for rate calculations */ ch->timestamp_created = time(NULL) - 30; tt_int_op(ch->timestamp_created, OP_GT, 0); tt_int_op(time(NULL), OP_GT, ch->timestamp_created); /* Put cells through it both ways to make the counters non-zero */ p_cell = packed_cell_new(); test_chan_accept_cells = 1; old_count = test_cells_written; channel_write_packed_cell(ch, p_cell); tt_int_op(test_cells_written, OP_EQ, old_count + 1); tt_u64_op(ch->n_bytes_xmitted, OP_GT, 0); tt_u64_op(ch->n_cells_xmitted, OP_GT, 0); /* Receive path */ channel_set_cell_handlers(ch, chan_test_cell_handler, chan_test_var_cell_handler); tt_ptr_op(channel_get_cell_handler(ch), OP_EQ, chan_test_cell_handler); tt_ptr_op(channel_get_var_cell_handler(ch), OP_EQ, chan_test_var_cell_handler); cell = tor_malloc_zero(sizeof(*cell)); old_count = test_chan_fixed_cells_recved; channel_process_cell(ch, cell); tt_int_op(test_chan_fixed_cells_recved, OP_EQ, old_count + 1); tt_u64_op(ch->n_bytes_recved, OP_GT, 0); tt_u64_op(ch->n_cells_recved, OP_GT, 0); /* Test channel_dump_statistics */ ch->describe_transport = chan_test_describe_transport; ch->dumpstats = chan_test_dumpstats; test_chan_should_be_canonical = 1; ch->is_canonical = test_chan_is_canonical; old_count = test_dumpstats_calls; channel_dump_statistics(ch, LOG_DEBUG); tt_int_op(test_dumpstats_calls, OP_EQ, old_count + 1); /* Close the channel */ channel_mark_for_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSING); chan_test_finish_close(ch); tt_int_op(ch->state, OP_EQ, CHANNEL_STATE_CLOSED); channel_run_cleanup(); ch = NULL; done: free_fake_channel(ch); tor_free(cell); UNMOCK(scheduler_channel_doesnt_want_writes); UNMOCK(scheduler_release_channel); return; }